pax_global_header00006660000000000000000000000064141255006360014514gustar00rootroot0000000000000052 comment=21af2aaec9e8948019e5189fa3fa5d2417f9eafa jss-5.0.0/000077500000000000000000000000001412550063600123155ustar00rootroot00000000000000jss-5.0.0/.classpath000066400000000000000000000015321412550063600143010ustar00rootroot00000000000000 jss-5.0.0/.copr/000077500000000000000000000000001412550063600133365ustar00rootroot00000000000000jss-5.0.0/.copr/Makefile000066400000000000000000000002441412550063600147760ustar00rootroot00000000000000srpm: dnf install -y git ./build.sh --with-timestamp --with-commit-id srpm if [[ "${outdir}" != "" ]]; then \ mv ${HOME}/build/jss/SRPMS/* ${outdir}; \ fi jss-5.0.0/.github/000077500000000000000000000000001412550063600136555ustar00rootroot00000000000000jss-5.0.0/.github/workflows/000077500000000000000000000000001412550063600157125ustar00rootroot00000000000000jss-5.0.0/.github/workflows/build-tests.yml000066400000000000000000000036761412550063600207100ustar00rootroot00000000000000name: Build Tests on: [push, pull_request] jobs: build-test: name: Build Test runs-on: ubuntu-latest strategy: matrix: os: - 'fedora:latest' - 'debian:testing' - 'ubuntu:rolling' # Disable CentOS due to missing dependencies # - 'centos:7' # - 'centos:8' container: ${{ matrix.os }} steps: - name: Clone repository uses: actions/checkout@v2 - name: Install Fedora/CentOS dependencies if: ${{ startsWith(matrix.os, 'fedora:') || startsWith(matrix.os, 'centos:') }} run: | dnf install -y dnf-plugins-core rpm-build dnf builddep -y --spec jss.spec - name: Install Debian/Ubuntu dependencies if: ${{ startsWith(matrix.os, 'debian:') || startsWith(matrix.os, 'ubuntu:') }} run: | apt-get update apt-get install -y \ cmake zip unzip \ g++ libnss3-dev libnss3-tools \ openjdk-11-jdk libcommons-lang3-java libslf4j-java junit4 - name: Build JSS binaries, Javadoc, and run tests run: ./build.sh # Compare JNI symbols in the code and in the version script. # If there are JNI symbols in the code but not in the version script -> fail. symbol-test: name: Symbol Test runs-on: ubuntu-latest steps: - name: Clone repository uses: actions/checkout@v2 - name: Get JNI symbols in the code run: | grep -iroh '^Java_org_mozilla[^(;]*' src/main/java/ | sort -u > /tmp/functions.txt cat /tmp/functions.txt - name: Get JNI symbols in the version script run: | grep -iroh '^Java_org_mozilla[^(;]*' lib/ | sort -u > /tmp/version.txt cat /tmp/version.txt - name: Compare JNI symbols run: | diff /tmp/functions.txt /tmp/version.txt || true comm -23 --check-order /tmp/functions.txt /tmp/version.txt > /tmp/diff.txt test ! -s /tmp/diff.txt jss-5.0.0/.github/workflows/code-analysis.yml000066400000000000000000000022271412550063600211730ustar00rootroot00000000000000name: Code Analysis on: [push, pull_request] jobs: build: name: Code analysis runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - name: Set up JDK 11 uses: actions/setup-java@v1 with: java-version: 11 - name: Cache SonarCloud packages uses: actions/cache@v1 with: path: ~/.sonar/cache key: ${{ runner.os }}-sonar restore-keys: ${{ runner.os }}-sonar - name: Cache Maven packages uses: actions/cache@v1 with: path: ~/.m2 key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} restore-keys: ${{ runner.os }}-m2 - name: Build and analyze with SonarCloud env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} run: > mvn -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.c.file.suffixes= -Dsonar.cpp.file.suffixes=- -Dsonar.objc.file.suffixes=- jss-5.0.0/.github/workflows/known_failures.yml000066400000000000000000000006511412550063600214650ustar00rootroot00000000000000name: Known Failing Tests on: [push, pull_request] jobs: test: runs-on: ubuntu-latest strategy: matrix: image: - 'fedora_rawhide' - 'fedora_sandbox' steps: - name: Clone the repository uses: actions/checkout@v2 - name: Build and Run the Docker Image run: bash tools/run_container.sh "${{ matrix.image }}" || echo "::warning ::Job exited with status $?" jss-5.0.0/.github/workflows/maven-tests.yml000066400000000000000000000007241412550063600207060ustar00rootroot00000000000000name: Maven Tests on: [push, pull_request] jobs: build: name: Building JSS runs-on: ubuntu-latest steps: - name: Clone repository uses: actions/checkout@v2 - name: Set up Java uses: actions/setup-java@v2 with: java-version: '11' distribution: 'adopt' - name: Build JSS run: mvn install - name: Build examples run: mvn compile working-directory: examples # TODO: Run examples jss-5.0.0/.github/workflows/pkcs11-tests.yml000066400000000000000000000061051412550063600207010ustar00rootroot00000000000000name: PKCS11 Tests on: [push, pull_request] jobs: init: name: Initializing Workflow runs-on: ubuntu-latest outputs: matrix: ${{ steps.init.outputs.matrix }} repo: ${{ steps.init.outputs.repo }} steps: - name: Clone repository uses: actions/checkout@v2 - name: Initialize workflow id: init env: BASE64_MATRIX: ${{ secrets.BASE64_MATRIX }} BASE64_REPO: ${{ secrets.BASE64_REPO }} run: | tests/bin/init-workflow.sh build: name: Building JSS needs: init runs-on: ubuntu-latest strategy: matrix: ${{ fromJSON(needs.init.outputs.matrix) }} steps: - name: Clone repository uses: actions/checkout@v2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 - name: Build runner image uses: docker/build-push-action@v2 with: context: . build-args: | OS_VERSION=${{ matrix.os }} COPR_REPO=${{ needs.init.outputs.repo }} BUILD_OPTS=--with-timestamp --with-commit-id tags: jss-runner target: jss-runner outputs: type=docker,dest=/tmp/jss-runner.tar - name: Upload runner image uses: actions/cache@v2 with: key: jss-runner-${{ matrix.os }} path: /tmp/jss-runner.tar pkcs11-constants-test: name: Testing PKCS11 Constants needs: [init, build] runs-on: ubuntu-latest env: SHARED: /tmp/workdir/jss strategy: matrix: ${{ fromJSON(needs.init.outputs.matrix) }} steps: - name: Clone repository uses: actions/checkout@v2 - name: Download runner image uses: actions/cache@v2 with: key: jss-runner-${{ matrix.os }} path: /tmp/jss-runner.tar - name: Load runner image run: docker load --input /tmp/jss-runner.tar - name: Run container run: | IMAGE=jss-runner \ NAME=jss \ HOSTNAME=jss.example.com \ tests/bin/runner-init.sh - name: Install dependencies run: docker exec jss dnf install -y nss-util-devel python2 python3 java-devel - name: Generate PKCS11 constants with Python 2 run: | docker exec jss python2 $SHARED/tools/build_pkcs11_constants.py \ --pkcs11t /usr/include/nss3/pkcs11t.h \ --pkcs11n /usr/include/nss3/pkcs11n.h \ -o PKCS11Constants-py2.java \ --verbose docker exec jss diff PKCS11Constants-py2.java $SHARED/src/main/java/org/mozilla/jss/pkcs11/PKCS11Constants.java - name: Generate PKCS11 constants with Python 3 run: | docker exec jss python3 $SHARED/tools/build_pkcs11_constants.py \ --pkcs11t /usr/include/nss3/pkcs11t.h \ --pkcs11n /usr/include/nss3/pkcs11n.h \ -o PKCS11Constants-py3.java \ --verbose docker exec jss diff PKCS11Constants-py3.java $SHARED/src/main/java/org/mozilla/jss/pkcs11/PKCS11Constants.java jss-5.0.0/.github/workflows/pki-tests.yml000066400000000000000000000135041412550063600203630ustar00rootroot00000000000000name: PKI Tests on: [push, pull_request] jobs: init: name: Initializing Workflow runs-on: ubuntu-latest outputs: matrix: ${{ steps.init.outputs.matrix }} repo: ${{ steps.init.outputs.repo }} steps: - name: Clone repository uses: actions/checkout@v2 - name: Initialize workflow id: init env: BASE64_MATRIX: ${{ secrets.BASE64_MATRIX }} BASE64_REPO: ${{ secrets.BASE64_REPO }} run: | tests/bin/init-workflow.sh build: name: Building JSS needs: init runs-on: ubuntu-latest strategy: matrix: ${{ fromJSON(needs.init.outputs.matrix) }} steps: - name: Clone repository uses: actions/checkout@v2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 - name: Build runner image uses: docker/build-push-action@v2 with: context: . build-args: | OS_VERSION=${{ matrix.os }} COPR_REPO=${{ needs.init.outputs.repo }} BUILD_OPTS=--with-timestamp --with-commit-id tags: jss-runner target: jss-runner outputs: type=docker,dest=/tmp/jss-runner.tar - name: Upload runner image uses: actions/upload-artifact@v2 with: name: jss-runner-${{ matrix.os }} path: /tmp/jss-runner.tar pki-build-test: name: Building PKI needs: [init, build] runs-on: ubuntu-latest env: SHARED: /tmp/workdir/jss strategy: matrix: ${{ fromJSON(needs.init.outputs.matrix) }} steps: - name: Clone repository uses: actions/checkout@v2 - name: Download runner image uses: actions/download-artifact@v2 with: name: jss-runner-${{ matrix.os }} path: /tmp - name: Load runner image run: docker load --input /tmp/jss-runner.tar - name: Run container run: | IMAGE=jss-runner \ NAME=pki \ HOSTNAME=pki.example.com \ tests/bin/runner-init.sh - name: Build PKI run: | docker exec pki dnf install -y git rpm-build docker exec pki git clone https://github.com/dogtagpki/pki docker exec pki dnf build-dep -y --spec pki/pki.spec docker exec pki pki/build.sh --with-timestamp --with-commit-id rpm docker exec pki bash -c "dnf install -y /root/build/pki/RPMS/*.rpm" ca-test: name: Installing CA needs: [init, build] runs-on: ubuntu-latest env: SHARED: /tmp/workdir/jss strategy: matrix: ${{ fromJSON(needs.init.outputs.matrix) }} steps: - name: Clone repository uses: actions/checkout@v2 - name: Download runner image uses: actions/download-artifact@v2 with: name: jss-runner-${{ matrix.os }} path: /tmp - name: Load runner image run: docker load --input /tmp/jss-runner.tar - name: Run container run: | IMAGE=jss-runner \ NAME=pki \ HOSTNAME=pki.example.com \ tests/bin/runner-init.sh - name: Install DS and PKI packages run: docker exec pki dnf install -y 389-ds-base pki-ca pki-tests - name: Install DS run: docker exec pki ${SHARED}/tests/bin/ds-create.sh - name: Install CA run: | docker exec pki pkispawn -f /usr/share/pki/server/examples/installation/ca.cfg -s CA -v # set buffer size to 0 so that revocation takes effect immediately docker exec pki pki-server ca-config-set auths.revocationChecking.bufferSize 0 # enable signed audit log docker exec pki pki-server ca-config-set log.instance.SignedAudit.logSigning true # restart PKI server docker exec pki pki-server restart --wait - name: Run PKI healthcheck run: docker exec pki pki-healthcheck --debug - name: Initialize PKI client run: | docker exec pki pki-server cert-export ca_signing --cert-file ca_signing.crt docker exec pki pki client-cert-import ca_signing --ca-cert ca_signing.crt docker exec pki pki info - name: Test CA certs run: | docker exec pki /usr/share/pki/tests/ca/bin/test-ca-signing-cert.sh docker exec pki /usr/share/pki/tests/ca/bin/test-subsystem-cert.sh docker exec pki /usr/share/pki/tests/ca/bin/test-ca-certs.sh - name: Test CA admin run: | docker exec pki pki client-cert-import \ --pkcs12 /root/.dogtag/pki-tomcat/ca_admin_cert.p12 \ --pkcs12-password-file /root/.dogtag/pki-tomcat/ca/pkcs12_password.conf docker exec pki pki -n caadmin ca-user-show caadmin - name: Test CA agent run: | docker exec pki /usr/share/pki/tests/ca/bin/ca-agent-create.sh docker exec pki /usr/share/pki/tests/ca/bin/ca-agent-cert-create.sh docker exec pki /usr/share/pki/tests/ca/bin/ca-agent-cert-revoke.sh docker exec pki /usr/share/pki/tests/ca/bin/ca-agent-cert-unrevoke.sh - name: Test CA auditor run: | docker exec pki /usr/share/pki/tests/ca/bin/test-ca-auditor-create.sh docker exec pki /usr/share/pki/tests/ca/bin/test-ca-auditor-cert.sh docker exec pki /usr/share/pki/tests/ca/bin/test-ca-auditor-logs.sh - name: Gather artifacts if: always() run: | tests/bin/ds-artifacts-save.sh pki tests/bin/pki-artifacts-save.sh pki - name: Remove CA run: docker exec pki pkidestroy -i pki-tomcat -s CA -v - name: Remove DS run: docker exec pki ${SHARED}/tests/bin/ds-remove.sh - name: Upload artifacts if: always() uses: actions/upload-artifact@v2 with: name: ca-${{ matrix.os }} path: | /tmp/artifacts/pki jss-5.0.0/.gitignore000066400000000000000000000004521412550063600143060ustar00rootroot00000000000000# Ignore build directories and artifacts /bin *.OBJ/ build/ src/*.a src/*.o target/ # These files are automatically generated from their .in equivalents org/mozilla/jss/util/jssver.h org/mozilla/jss/jssconfig.h src/main/java/org/mozilla/jss/util/jssver.h src/main/java/org/mozilla/jss/jssconfig.h jss-5.0.0/.gitlab-ci.yml000066400000000000000000000012321412550063600147470ustar00rootroot00000000000000image: fedora sync: script: - echo "Synchronizing $CI_COMMIT_BRANCH branch from $UPSTREAM_URL to $CI_PROJECT_URL" - dnf install -y git - git remote set-url origin https://sync:$ACCESS_TOKEN@$CI_SERVER_HOST/$CI_PROJECT_PATH.git - git remote remove upstream || true - git remote add upstream $UPSTREAM_URL - git remote -v - git fetch upstream $CI_COMMIT_BRANCH - git checkout upstream/$CI_COMMIT_BRANCH - git log origin/$CI_COMMIT_BRANCH..upstream/$CI_COMMIT_BRANCH --oneline - GIT_SSL_NO_VERIFY=true git push origin HEAD:$CI_COMMIT_BRANCH rules: - if: $SYNC == "true" tags: # Use shared runners. - shared jss-5.0.0/.hgignore000066400000000000000000000000621412550063600141160ustar00rootroot00000000000000syntax: glob *~ *OPT.OBJ/* *DBG.OBJ/* *DBG.OBJD/* jss-5.0.0/.project000066400000000000000000000005521412550063600137660ustar00rootroot00000000000000 jss org.eclipse.jdt.core.javabuilder org.eclipse.jdt.core.javanature jss-5.0.0/.settings/000077500000000000000000000000001412550063600142335ustar00rootroot00000000000000jss-5.0.0/.settings/org.eclipse.jdt.core.prefs000066400000000000000000000561231412550063600212240ustar00rootroot00000000000000eclipse.preferences.version=1 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 org.eclipse.jdt.core.formatter.alignment_for_assignment=0 org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 org.eclipse.jdt.core.formatter.blank_lines_after_package=1 org.eclipse.jdt.core.formatter.blank_lines_before_field=0 org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 org.eclipse.jdt.core.formatter.blank_lines_before_method=1 org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 org.eclipse.jdt.core.formatter.blank_lines_before_package=0 org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false org.eclipse.jdt.core.formatter.comment.format_block_comments=false org.eclipse.jdt.core.formatter.comment.format_header=false org.eclipse.jdt.core.formatter.comment.format_html=true org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true org.eclipse.jdt.core.formatter.comment.format_line_comments=false org.eclipse.jdt.core.formatter.comment.format_source_code=true org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true org.eclipse.jdt.core.formatter.comment.indent_root_tags=true org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert org.eclipse.jdt.core.formatter.comment.line_length=120 org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false org.eclipse.jdt.core.formatter.compact_else_if=true org.eclipse.jdt.core.formatter.continuation_indentation=2 org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=false org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true org.eclipse.jdt.core.formatter.indent_empty_lines=false org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false org.eclipse.jdt.core.formatter.indentation.size=8 org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert org.eclipse.jdt.core.formatter.join_lines_in_comments=false org.eclipse.jdt.core.formatter.join_wrapped_lines=false org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false org.eclipse.jdt.core.formatter.lineSplit=120 org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true org.eclipse.jdt.core.formatter.tabulation.char=space org.eclipse.jdt.core.formatter.tabulation.size=4 org.eclipse.jdt.core.formatter.use_on_off_tags=false org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true jss-5.0.0/.settings/org.eclipse.jdt.ui.prefs000066400000000000000000000052561412550063600207120ustar00rootroot00000000000000eclipse.preferences.version=1 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true formatter_profile=_PKI Project Profile formatter_settings_version=12 sp_cleanup.add_default_serial_version_id=true sp_cleanup.add_generated_serial_version_id=false sp_cleanup.add_missing_annotations=false sp_cleanup.add_missing_deprecated_annotations=true sp_cleanup.add_missing_methods=false sp_cleanup.add_missing_nls_tags=false sp_cleanup.add_missing_override_annotations=true sp_cleanup.add_missing_override_annotations_interface_methods=true sp_cleanup.add_serial_version_id=false sp_cleanup.always_use_blocks=true sp_cleanup.always_use_parentheses_in_expressions=false sp_cleanup.always_use_this_for_non_static_field_access=false sp_cleanup.always_use_this_for_non_static_method_access=false sp_cleanup.convert_to_enhanced_for_loop=false sp_cleanup.correct_indentation=false sp_cleanup.format_source_code=false sp_cleanup.format_source_code_changes_only=false sp_cleanup.make_local_variable_final=false sp_cleanup.make_parameters_final=false sp_cleanup.make_private_fields_final=true sp_cleanup.make_type_abstract_if_missing_method=false sp_cleanup.make_variable_declarations_final=false sp_cleanup.never_use_blocks=false sp_cleanup.never_use_parentheses_in_expressions=true sp_cleanup.on_save_use_additional_actions=true sp_cleanup.organize_imports=true sp_cleanup.qualify_static_field_accesses_with_declaring_class=false sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true sp_cleanup.qualify_static_member_accesses_with_declaring_class=false sp_cleanup.qualify_static_method_accesses_with_declaring_class=false sp_cleanup.remove_private_constructors=true sp_cleanup.remove_trailing_whitespaces=true sp_cleanup.remove_trailing_whitespaces_all=true sp_cleanup.remove_trailing_whitespaces_ignore_empty=false sp_cleanup.remove_unnecessary_casts=true sp_cleanup.remove_unnecessary_nls_tags=false sp_cleanup.remove_unused_imports=true sp_cleanup.remove_unused_local_variables=false sp_cleanup.remove_unused_private_fields=true sp_cleanup.remove_unused_private_members=false sp_cleanup.remove_unused_private_methods=true sp_cleanup.remove_unused_private_types=true sp_cleanup.sort_members=false sp_cleanup.sort_members_all=false sp_cleanup.use_blocks=false sp_cleanup.use_blocks_only_for_return_and_throw=false sp_cleanup.use_parentheses_in_expressions=false sp_cleanup.use_this_for_non_static_field_access=false sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true sp_cleanup.use_this_for_non_static_method_access=false sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true jss-5.0.0/CMakeLists.txt000066400000000000000000000071571412550063600150670ustar00rootroot00000000000000# This is the CMakeLists.txt for the JSS Project. project(jss) # Required cmake version; set a 3.14.2 since we need LINK_OPTIONS in # try_compile. cmake_minimum_required(VERSION 3.14.0) # Source our custom CMake modules; this includes NSS and NSPR modules from # PKI and the JSSConfig and JSSCommon modules. set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) # Define optional variables and conditionals. if (DEFINED ENV{CHECK_DEPRECATION}) set(CHECK_DEPRECATION_ENV TRUE) endif() option(CHECK_DEPRECATION "When enabled, utilize the deprecation checking functionality of the java compiler." ${CHECK_DEPRECATION_ENV}) if (CHECK_DEPRECATION) list(APPEND JSS_JAVAC_FLAGS "-Xlint:deprecation") endif() if (DEFINED ENV{FIPS_ENABLED}) set(FIPS_ENABLED_ENV TRUE) endif() option(FIPS_ENABLED "When enabled, disable certain tests which don't work in FIPS mode. This should only be specified when the host system is in FIPS mode." ${FIPS_ENABLED_ENV}) if (DEFINED ENV{SANDBOX}) set(SANDBOX_ENV TRUE) endif() option(SANDBOX "When enabled, expect to find nss and nspr from the parent (sandbox) directory instead of using the system-installed versions of the libraries." ${SANDBOX_ENV}) if (DEFINED ENV{TEST_VALGRIND}) set(TEST_VALGRIND_ENV TRUE) endif() option(TEST_VALGRIND "When enabled, run the entire test suite under Valgrind. This will be noisy as JSS can't clean up NSS initialization and the JVM itself leaks." ${TEST_VALGRIND_ENV}) # Build a debug build by default when no type is specified on the command line if(NOT (DEFINED CMAKE_BUILD_TYPE)) set(CMAKE_BUILD_TYPE "Debug") endif() if (DEFINED ENV{WITH_INTERNET}) set(TEST_WITH_INTERNET_ENV TRUE) endif() option(TEST_WITH_INTERNET "When enabled, runs various tests which require an internet connection. " ${TEST_WITH_INTERNET_ENV}) option(WITH_JAVADOC "Build Javadoc package." TRUE) # Find NSPR and NSS Libraries. find_package(NSPR REQUIRED) find_package(NSS REQUIRED) # Find Java and JNI packages; this sets CMake wariables like # Java_JAVAC_EXECUTABLE. find_package(Java REQUIRED) find_package(JNI REQUIRED) # Shims for older CMake versions without useful features. include(Shims) # Since we found Java, include UseJava to provide the find_jar function. include(UseJava) # These includes are required for the macro check_symbol_exists and # check_struct_has_member in jss_config(). include(CheckSymbolExists) include(CheckStructHasMember) # Load JSSConfig module; this defines the jss_config() macro which defines # JSS-specific configuration values. include(JSSConfig) # Load JSSCommon module; this defines the jss_build() macros which defines # the JSS build procedure. include(JSSCommon) # Load JSSTests module; this defines the jss_tests() macro which defines the # JSS test procedure. include(JSSTests) jss_config() jss_build() jss_tests() install( FILES ${CMAKE_CURRENT_BINARY_DIR}/jss.jar DESTINATION ${JAVA_LIB_INSTALL_DIR} ) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/libjss.so DESTINATION ${JSS_LIB_INSTALL_DIR} PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE ) install( CODE "execute_process( COMMAND ln -sf ${JAVA_LIB_INSTALL_DIR}/jss.jar \$ENV{DESTDIR}${JSS_LIB_INSTALL_DIR}/jss.jar )" ) if(WITH_JAVADOC) install( DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/docs/ DESTINATION ${CMAKE_INSTALL_PREFIX}/share/javadoc/jss ) install( FILES jss.html MPL-1.1.txt gpl.txt lgpl.txt DESTINATION ${CMAKE_INSTALL_PREFIX}/share/javadoc/jss ) endif(WITH_JAVADOC) jss-5.0.0/Dockerfile000066400000000000000000000022371412550063600143130ustar00rootroot00000000000000# # Copyright Red Hat, Inc. # # SPDX-License-Identifier: GPL-2.0-or-later # ARG OS_VERSION="latest" ARG COPR_REPO="@pki/master" ################################################################################ FROM registry.fedoraproject.org/fedora:$OS_VERSION AS jss-builder ARG COPR_REPO ARG BUILD_OPTS # Enable COPR repo if specified RUN if [ -n "$COPR_REPO" ]; then dnf install -y dnf-plugins-core; dnf copr enable -y $COPR_REPO; fi # Import source COPY . /tmp/src/ WORKDIR /tmp/src # Build packages RUN dnf install -y git rpm-build RUN dnf builddep -y --spec jss.spec RUN ./build.sh $BUILD_OPTS --work-dir=../build rpm ################################################################################ FROM registry.fedoraproject.org/fedora:$OS_VERSION AS jss-runner ARG COPR_REPO EXPOSE 389 8080 8443 # Enable COPR repo if specified RUN if [ -n "$COPR_REPO" ]; then dnf install -y dnf-plugins-core; dnf copr enable -y $COPR_REPO; fi # Import packages COPY --from=jss-builder /tmp/build/RPMS /tmp/RPMS/ # Install packages RUN dnf localinstall -y /tmp/RPMS/*; rm -rf /tmp/RPMS # Install systemd to run the container RUN dnf install -y systemd CMD [ "/usr/sbin/init" ] jss-5.0.0/MPL-1.1.txt000066400000000000000000000622331412550063600140110ustar00rootroot00000000000000 MOZILLA PUBLIC LICENSE Version 1.1 --------------- 1. Definitions. 1.0.1. "Commercial Use" means distribution or otherwise making the Covered Code available to a third party. 1.1. "Contributor" means each entity that creates or contributes to the creation of Modifications. 1.2. "Contributor Version" means the combination of the Original Code, prior Modifications used by a Contributor, and the Modifications made by that particular Contributor. 1.3. "Covered Code" means the Original Code or Modifications or the combination of the Original Code and Modifications, in each case including portions thereof. 1.4. "Electronic Distribution Mechanism" means a mechanism generally accepted in the software development community for the electronic transfer of data. 1.5. "Executable" means Covered Code in any form other than Source Code. 1.6. "Initial Developer" means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A. 1.7. "Larger Work" means a work which combines Covered Code or portions thereof with code not governed by the terms of this License. 1.8. "License" means this document. 1.8.1. "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently acquired, any and all of the rights conveyed herein. 1.9. "Modifications" means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. When Covered Code is released as a series of files, a Modification is: A. Any addition to or deletion from the contents of a file containing Original Code or previous Modifications. B. Any new file that contains any part of the Original Code or previous Modifications. 1.10. "Original Code" means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code, and which, at the time of its release under this License is not already Covered Code governed by this License. 1.10.1. "Patent Claims" means any patent claim(s), now owned or hereafter acquired, including without limitation, method, process, and apparatus claims, in any patent Licensable by grantor. 1.11. "Source Code" means the preferred form of the Covered Code for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control compilation and installation of an Executable, or source code differential comparisons against either the Original Code or another well known, available Covered Code of the Contributor's choice. The Source Code can be in a compressed or archival form, provided the appropriate decompression or de-archiving software is widely available for no charge. 1.12. "You" (or "Your") means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, "You" includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2. Source Code License. 2.1. The Initial Developer Grant. The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: (a) under intellectual property rights (other than patent or trademark) Licensable by Initial Developer to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, and/or as part of a Larger Work; and (b) under Patents Claims infringed by the making, using or selling of Original Code, to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Code (or portions thereof). (c) the licenses granted in this Section 2.1(a) and (b) are effective on the date Initial Developer first distributes Original Code under the terms of this License. (d) Notwithstanding Section 2.1(b) above, no patent license is granted: 1) for code that You delete from the Original Code; 2) separate from the Original Code; or 3) for infringements caused by: i) the modification of the Original Code or ii) the combination of the Original Code with other software or devices. 2.2. Contributor Grant. Subject to third party intellectual property claims, each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license (a) under intellectual property rights (other than patent or trademark) Licensable by Contributor, to use, reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor (or portions thereof) either on an unmodified basis, with other Modifications, as Covered Code and/or as part of a Larger Work; and (b) under Patent Claims infringed by the making, using, or selling of Modifications made by that Contributor either alone and/or in combination with its Contributor Version (or portions of such combination), to make, use, sell, offer for sale, have made, and/or otherwise dispose of: 1) Modifications made by that Contributor (or portions thereof); and 2) the combination of Modifications made by that Contributor with its Contributor Version (or portions of such combination). (c) the licenses granted in Sections 2.2(a) and 2.2(b) are effective on the date Contributor first makes Commercial Use of the Covered Code. (d) Notwithstanding Section 2.2(b) above, no patent license is granted: 1) for any code that Contributor has deleted from the Contributor Version; 2) separate from the Contributor Version; 3) for infringements caused by: i) third party modifications of Contributor Version or ii) the combination of Modifications made by that Contributor with other software (except as part of the Contributor Version) or other devices; or 4) under Patent Claims infringed by Covered Code in the absence of Modifications made by that Contributor. 3. Distribution Obligations. 3.1. Application of License. The Modifications which You create or to which You contribute are governed by the terms of this License, including without limitation Section 2.2. The Source Code version of Covered Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or restricts the applicable version of this License or the recipients' rights hereunder. However, You may include an additional document offering the additional rights described in Section 3.5. 3.2. Availability of Source Code. Any Modification which You create or to which You contribute must be made available in Source Code form under the terms of this License either on the same media as an Executable version or via an accepted Electronic Distribution Mechanism to anyone to whom you made an Executable version available; and if made available via Electronic Distribution Mechanism, must remain available for at least twelve (12) months after the date it initially became available, or at least six (6) months after a subsequent version of that particular Modification has been made available to such recipients. You are responsible for ensuring that the Source Code version remains available even if the Electronic Distribution Mechanism is maintained by a third party. 3.3. Description of Modifications. You must cause all Covered Code to which You contribute to contain a file documenting the changes You made to create that Covered Code and the date of any change. You must include a prominent statement that the Modification is derived, directly or indirectly, from Original Code provided by the Initial Developer and including the name of the Initial Developer in (a) the Source Code, and (b) in any notice in an Executable version or related documentation in which You describe the origin or ownership of the Covered Code. 3.4. Intellectual Property Matters (a) Third Party Claims. If Contributor has knowledge that a license under a third party's intellectual property rights is required to exercise the rights granted by such Contributor under Sections 2.1 or 2.2, Contributor must include a text file with the Source Code distribution titled "LEGAL" which describes the claim and the party making the claim in sufficient detail that a recipient will know whom to contact. If Contributor obtains such knowledge after the Modification is made available as described in Section 3.2, Contributor shall promptly modify the LEGAL file in all copies Contributor makes available thereafter and shall take other steps (such as notifying appropriate mailing lists or newsgroups) reasonably calculated to inform those who received the Covered Code that new knowledge has been obtained. (b) Contributor APIs. If Contributor's Modifications include an application programming interface and Contributor has knowledge of patent licenses which are reasonably necessary to implement that API, Contributor must also include this information in the LEGAL file. (c) Representations. Contributor represents that, except as disclosed pursuant to Section 3.4(a) above, Contributor believes that Contributor's Modifications are Contributor's original creation(s) and/or Contributor has sufficient rights to grant the rights conveyed by this License. 3.5. Required Notices. You must duplicate the notice in Exhibit A in each file of the Source Code. If it is not possible to put such notice in a particular Source Code file due to its structure, then You must include such notice in a location (such as a relevant directory) where a user would be likely to look for such a notice. If You created one or more Modification(s) You may add your name as a Contributor to the notice described in Exhibit A. You must also duplicate this License in any documentation for the Source Code where You describe recipients' rights or ownership rights relating to Covered Code. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. You must make it absolutely clear than any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability terms You offer. 3.6. Distribution of Executable Versions. You may distribute Covered Code in Executable form only if the requirements of Section 3.1-3.5 have been met for that Covered Code, and if You include a notice stating that the Source Code version of the Covered Code is available under the terms of this License, including a description of how and where You have fulfilled the obligations of Section 3.2. The notice must be conspicuously included in any notice in an Executable version, related documentation or collateral in which You describe recipients' rights relating to the Covered Code. You may distribute the Executable version of Covered Code or ownership rights under a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License and that the license for the Executable version does not attempt to limit or alter the recipient's rights in the Source Code version from the rights set forth in this License. If You distribute the Executable version under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer or any Contributor. You hereby agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer or such Contributor as a result of any such terms You offer. 3.7. Larger Works. You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Covered Code. 4. Inability to Comply Due to Statute or Regulation. If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Covered Code due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 3.4 and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. 5. Application of this License. This License applies to code to which the Initial Developer has attached the notice in Exhibit A and to related Covered Code. 6. Versions of the License. 6.1. New Versions. Netscape Communications Corporation ("Netscape") may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number. 6.2. Effect of New Versions. Once Covered Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Covered Code under the terms of any subsequent version of the License published by Netscape. No one other than Netscape has the right to modify the terms applicable to Covered Code created under this License. 6.3. Derivative Works. If You create or use a modified version of this License (which you may only do in order to apply it to code which is not already Covered Code governed by this License), You must (a) rename Your license so that the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", "MPL", "NPL" or any confusingly similar phrase do not appear in your license (except to note that your license differs from this License) and (b) otherwise make it clear that Your version of the license contains terms which differ from the Mozilla Public License and Netscape Public License. (Filling in the name of the Initial Developer, Original Code or Contributor in the notice described in Exhibit A shall not of themselves be deemed to be modifications of this License.) 7. DISCLAIMER OF WARRANTY. COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. 8. TERMINATION. 8.1. This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Covered Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. 8.2. If You initiate litigation by asserting a patent infringement claim (excluding declatory judgment actions) against Initial Developer or a Contributor (the Initial Developer or Contributor against whom You file such action is referred to as "Participant") alleging that: (a) such Participant's Contributor Version directly or indirectly infringes any patent, then any and all rights granted by such Participant to You under Sections 2.1 and/or 2.2 of this License shall, upon 60 days notice from Participant terminate prospectively, unless if within 60 days after receipt of notice You either: (i) agree in writing to pay Participant a mutually agreeable reasonable royalty for Your past and future use of Modifications made by such Participant, or (ii) withdraw Your litigation claim with respect to the Contributor Version against such Participant. If within 60 days of notice, a reasonable royalty and payment arrangement are not mutually agreed upon in writing by the parties or the litigation claim is not withdrawn, the rights granted by Participant to You under Sections 2.1 and/or 2.2 automatically terminate at the expiration of the 60 day notice period specified above. (b) any software, hardware, or device, other than such Participant's Contributor Version, directly or indirectly infringes any patent, then any rights granted to You by such Participant under Sections 2.1(b) and 2.2(b) are revoked effective as of the date You first made, used, sold, distributed, or had made, Modifications made by that Participant. 8.3. If You assert a patent infringement claim against Participant alleging that such Participant's Contributor Version directly or indirectly infringes any patent where such claim is resolved (such as by license or settlement) prior to the initiation of patent infringement litigation, then the reasonable value of the licenses granted by such Participant under Sections 2.1 or 2.2 shall be taken into account in determining the amount or value of any payment or license. 8.4. In the event of termination under Sections 8.1 or 8.2 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or any distributor hereunder prior to termination shall survive termination. 9. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. 10. U.S. GOVERNMENT END USERS. The Covered Code is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer software" and "commercial computer software documentation," as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Covered Code with only those rights set forth herein. 11. MISCELLANEOUS. This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by California law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in the United States of America, any litigation relating to this License shall be subject to the jurisdiction of the Federal Courts of the Northern District of California, with venue lying in Santa Clara County, California, with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys' fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. 12. RESPONSIBILITY FOR CLAIMS. As between Initial Developer and the Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of its utilization of rights under this License and You agree to work with Initial Developer and Contributors to distribute such responsibility on an equitable basis. Nothing herein is intended or shall be deemed to constitute any admission of liability. 13. MULTIPLE-LICENSED CODE. Initial Developer may designate portions of the Covered Code as "Multiple-Licensed". "Multiple-Licensed" means that the Initial Developer permits you to utilize portions of the Covered Code under Your choice of the NPL or the alternative licenses, if any, specified by the Initial Developer in the file described in Exhibit A. EXHIBIT A -Mozilla Public License. ``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 Initial Developer of the Original Code is ________________________. Portions created by ______________________ are Copyright (C) ______ _______________________. All Rights Reserved. Contributor(s): ______________________________________. Alternatively, the contents of this file may be used under the terms of the _____ license (the "[___] License"), in which case the provisions of [______] License are applicable instead of those above. If you wish to allow use of your version of this file only under the terms of the [____] License 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 [___] License. If you do not delete the provisions above, a recipient may use your version of this file under either the MPL or the [___] License." [NOTE: The text of this Exhibit A may differ slightly from the text of the notices in the Source Code files of the Original Code. You should use the text of this Exhibit A rather than the text found in the Original Code Source Code for Your Modifications.] jss-5.0.0/README.md000066400000000000000000000053051412550063600135770ustar00rootroot00000000000000Network Security Services for Java (JSS) ======================================== Overview -------- **Network Security Services for Java** is a Java interface to [NSS](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS). JSS supports most of the security standards and encryption technologies supported by NSS. JSS also provides a pure Java interface for ASN.1 types and BER/DER encoding. * Website: http://www.dogtagpki.org/wiki/JSS * Issues: https://github.com/dogtagpki/jss/issues * Archive: https://github.com/dogtagpki/jss-archive * Javadocs: https://dogtagpki.github.io/jss **NOTICE:** As of JSS version 4.5.1, the legacy build instructions will not work; the build system has been completely replaced with CMake. Dependencies ------------ This project has the following dependencies: - [NSPR](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSPR) - [NSS](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS) - Minimum version: 3.44 - Recommended version: 3.48 and above - A c and c++ compiler such as [gcc](ttps://gcc.gnu.org/) - [zlib](https://zlib.net/) - [OpenJDK 1.8.0 or newer](https://openjdk.java.net/) - [CMake](https://cmake.org/) - [Apache Commons Lang](https://commons.apache.org/proper/commons-lang/) - [SLF4J](https://www.slf4j.org/) - [JUnit 4](https://junit.org/junit4/) To install these dependencies on Fedora, execute the following: sudo dnf install apache-commons-lang gcc-c++ java-devel jpackage-utils \ slf4j zlib-devel nss-tools nss-devel \ cmake junit To install these dependencies on Debian, execute the following: sudo apt-get install build-essential libcommons-lang-java libnss3-dev \ libslf4j-java default-jdk pkg-config zlib1g-dev \ libnss3-tools cmake zip unzip \ junit4 Building -------- To build JSS and make a best effort to detect environment variables: git clone https://github.com/dogtagpki/jss cd jss/build && cmake .. make all test Alternatively, to build a RPM distribution of JSS: git clone https://github.com/dogtagpki/jss cd jss ./build.sh rpm To view more detailed instructions for building JSS, please refer to the build documentation: [`docs/building.md`](docs/building.md). In Distributions ---------------- JSS is currently shipped in Fedora-based distributions under the package name `jss`; to install issue `sudo dnf install jss`. JSS is also shipped in Debian-based distributions under the package name `libjss-java`; to install, issue `sudo apt-get install libjss-java`. Contact Us ---------- See [Contact Us](https://github.com/dogtagpki/pki/wiki/Contact-Us). jss-5.0.0/azure-pipelines.yml000066400000000000000000000046521412550063600161630ustar00rootroot00000000000000# Workaround to install sudo # https://github.com/Microsoft/azure-pipelines-agent/issues/2043#issuecomment-687983301 resources: containers: - container: debian_testing image: debian:testing options: '--name ci-container -v /usr/bin/docker:/tmp/docker:ro' - container: ubuntu_rolling image: ubuntu:rolling options: '--name ci-container -v /usr/bin/docker:/tmp/docker:ro' jobs: - job: BuildTest pool: vmImage: ubuntu-latest strategy: matrix: fedora_latest: image: fedora:latest debian_testing: image: debian_testing ubuntu_rolling: image: ubuntu_rolling # Disable CentOS due to missing dependencies # centos_7: # image: centos:7 # centos_8: # image: centos:8 container: $[variables['image']] steps: - script: | sudo dnf install -y dnf-plugins-core rpm-build sudo dnf builddep -y --spec jss.spec condition: or(startsWith(variables.image, 'fedora:'), startsWith(variables.image, 'centos:')) displayName: Install Fedora/CentOS dependencies - script: | # Workaround to install sudo # https://github.com/Microsoft/azure-pipelines-agent/issues/2043#issuecomment-687983301 /tmp/docker exec -t -u 0 ci-container \ apt-get update /tmp/docker exec -t -u 0 -e DEBIAN_FRONTEND=noninteractive ci-container \ apt-get -o Dpkg::Options::="--force-confold" -y install sudo sudo apt-get install -y \ cmake zip unzip \ g++ libnss3-dev libnss3-tools \ openjdk-11-jdk libcommons-lang3-java libslf4j-java junit4 condition: or(startsWith(variables.image, 'debian_'), startsWith(variables.image, 'ubuntu_')) displayName: Install Debian/Ubuntu dependencies - script: ./build.sh displayName: Build JSS binaries, Javadoc, and run tests - job: SymbolTest pool: vmImage: ubuntu-latest steps: - script: | grep -iroh '^Java_org_mozilla[^(;]*' src/main/java/ | sort -u > /tmp/functions.txt cat /tmp/functions.txt displayName: Get JNI symbols in the code - script: | grep -iroh '^Java_org_mozilla[^(;]*' lib/ | sort -u > /tmp/version.txt cat /tmp/version.txt displayName: Get JNI symbols in the version script - script: | diff /tmp/functions.txt /tmp/version.txt || true comm -23 --check-order /tmp/functions.txt /tmp/version.txt > /tmp/diff.txt test ! -s /tmp/diff.txt displayName: Compare JNI symbols jss-5.0.0/build.sh000077500000000000000000000307361412550063600137640ustar00rootroot00000000000000#!/bin/bash -e # BEGIN COPYRIGHT BLOCK # (C) 2018 Red Hat, Inc. # All rights reserved. # END COPYRIGHT BLOCK SCRIPT_PATH="$(readlink -f "$0")" SCRIPT_NAME="$(basename "$SCRIPT_PATH")" SRC_DIR="$(dirname "$SCRIPT_PATH")" NAME=jss WORK_DIR="$HOME/build/$NAME" JAVA_LIB_DIR="/usr/lib/java" if [ "$HOSTTYPE" = "x86_64" ]; then JSS_LIB_DIR="/usr/lib64/jss" else JSS_LIB_DIR="/usr/lib/jss" fi INSTALL_DIR= SOURCE_TAG= SPEC_TEMPLATE= VERSION= RELEASE= WITH_TIMESTAMP= WITH_COMMIT_ID= DIST= WITHOUT_JAVADOC= WITHOUT_TEST= VERBOSE= DEBUG= usage() { echo "Usage: $SCRIPT_NAME [OPTIONS] " echo echo "Options:" echo " --work-dir= Working directory (default: $WORK_DIR)." echo " --java-lib-dir= Java library directory (default: $JAVA_LIB_DIR)." echo " --jss-lib-dir= JSS library directory (default: $JSS_LIB_DIR)." echo " --install-dir= Installation directory." echo " --source-tag= Generate RPM sources from a source tag." echo " --spec= Use the specified RPM spec." echo " --version= Use the specified version." echo " --release= Use the specified release." echo " --with-timestamp Append timestamp to release number." echo " --with-commit-id Append commit ID to release number." echo " --dist= Distribution name (e.g. fc28)." echo " --without-javadoc Do not build Javadoc package." echo " --without-test Do not run unit tests." echo " -v,--verbose Run in verbose mode." echo " --debug Run in debug mode." echo " --help Show help message." echo echo "Target:" echo " dist Build JSS binaries (default)." echo " install Install JSS binaries." echo " src Generate RPM sources." echo " spec Generate RPM spec." echo " srpm Build SRPM package." echo " rpm Build RPM packages." } generate_rpm_sources() { TARBALL="$NAME-$VERSION${_PHASE}.tar.gz" if [ "$SOURCE_TAG" != "" ] ; then if [ "$VERBOSE" = true ] ; then echo "Generating $TARBALL from $SOURCE_TAG tag" fi git -C "$SRC_DIR" \ archive \ --format=tar.gz \ --prefix "$NAME-$VERSION${_PHASE}/" \ -o "$WORK_DIR/SOURCES/$TARBALL" \ $SOURCE_TAG if [ "$SOURCE_TAG" != "HEAD" ] ; then TAG_ID="$(git -C "$SRC_DIR" rev-parse $SOURCE_TAG)" HEAD_ID="$(git -C "$SRC_DIR" rev-parse HEAD)" if [ "$TAG_ID" != "$HEAD_ID" ] ; then generate_patch fi fi return fi if [ "$VERBOSE" = true ] ; then echo "Generating $TARBALL" fi tar czf "$WORK_DIR/SOURCES/$TARBALL" \ --transform "s,^./,$NAME-$VERSION${_PHASE}/," \ --exclude .git \ --exclude bin \ -C "$SRC_DIR" \ . } generate_patch() { PATCH="$NAME-$VERSION-$RELEASE.patch" if [ "$VERBOSE" = true ] ; then echo "Generating $PATCH for all changes since $SOURCE_TAG tag" fi git -C "$SRC_DIR" \ format-patch \ --stdout \ $SOURCE_TAG \ > "$WORK_DIR/SOURCES/$PATCH" } generate_rpm_spec() { RPM_SPEC="$NAME.spec" if [ "$VERBOSE" = true ] ; then echo "Generating $RPM_SPEC" fi # hard-code timestamp commands="s/%{?_timestamp}/${_TIMESTAMP}/g" # hard-code commit ID commands="${commands}; s/%{?_commit_id}/${_COMMIT_ID}/g" # hard-code phase commands="${commands}; s/%{?_phase}/${_PHASE}/g" # hard-code patch if [ "$PATCH" != "" ] ; then commands="${commands}; s/# Patch: jss-VERSION-RELEASE.patch/Patch: $PATCH/g" fi # hard-code Javadoc option if [ "$WITHOUT_JAVADOC" = true ] ; then # convert bcond_without into bcond_with such that Javadoc package is not built by default commands="${commands}; s/%\(bcond_without *javadoc\)\$/# \1\n%bcond_with javadoc/g" fi # hard-code test option if [ "$WITHOUT_TEST" = true ] ; then # convert bcond_without into bcond_with such that unit tests do not run by default commands="${commands}; s/%\(bcond_without *test\)\$/# \1\n%bcond_with test/g" fi sed "$commands" "$SPEC_TEMPLATE" > "$WORK_DIR/SPECS/$RPM_SPEC" # rpmlint "$WORK_DIR/SPECS/$RPM_SPEC" } while getopts v-: arg ; do case $arg in v) VERBOSE=true ;; -) LONG_OPTARG="${OPTARG#*=}" case $OPTARG in work-dir=?*) WORK_DIR="$(readlink -f "$LONG_OPTARG")" ;; java-lib-dir=?*) JAVA_LIB_DIR="$(readlink -f "$LONG_OPTARG")" ;; jss-lib-dir=?*) JSS_LIB_DIR="$(readlink -f "$LONG_OPTARG")" ;; install-dir=?*) INSTALL_DIR="$(readlink -f "$LONG_OPTARG")" ;; source-tag=?*) SOURCE_TAG="$LONG_OPTARG" ;; spec=?*) SPEC_TEMPLATE="$LONG_OPTARG" ;; version=?*) VERSION="$LONG_OPTARG" ;; release=?*) RELEASE="$LONG_OPTARG" ;; with-timestamp) WITH_TIMESTAMP=true ;; with-commit-id) WITH_COMMIT_ID=true ;; dist=?*) DIST="$LONG_OPTARG" ;; without-javadoc) WITHOUT_JAVADOC=true ;; without-test) WITHOUT_TEST=true ;; verbose) VERBOSE=true ;; debug) VERBOSE=true DEBUG=true ;; help) usage exit ;; '') break # "--" terminates argument processing ;; work-dir* | java-lib-dir* | jss-lib-dir* | install-dir* | source-tag* | spec* | version* | release* | dist*) echo "ERROR: Missing argument for --$OPTARG option" >&2 exit 1 ;; *) echo "ERROR: Illegal option --$OPTARG" >&2 exit 1 ;; esac ;; \?) exit 1 # getopts already reported the illegal option ;; esac done # remove parsed options and args from $@ list shift $((OPTIND-1)) if [ "$#" -lt 1 ] ; then BUILD_TARGET=dist else BUILD_TARGET=$1 fi if [ "$DEBUG" = true ] ; then echo "WORK_DIR: $WORK_DIR" echo "JAVA_LIB_DIR: $JAVA_LIB_DIR" echo "JSS_LIB_DIR: $JSS_LIB_DIR" echo "INSTALL_DIR: $INSTALL_DIR" echo "BUILD_TARGET: $BUILD_TARGET" fi if [ "$BUILD_TARGET" != "dist" ] && [ "$BUILD_TARGET" != "install" ] && [ "$BUILD_TARGET" != "src" ] && [ "$BUILD_TARGET" != "spec" ] && [ "$BUILD_TARGET" != "srpm" ] && [ "$BUILD_TARGET" != "rpm" ] ; then echo "ERROR: Invalid build target: $BUILD_TARGET" >&2 exit 1 fi mkdir -p "$WORK_DIR" cd "$WORK_DIR" if [ "$BUILD_TARGET" = "dist" ] ; then if [ "$VERBOSE" = true ] ; then echo "Building $NAME" fi OPTIONS=() OPTIONS+=(-DVERSION=$VERSION) if [ "$JAVA_HOME" != "" ] ; then OPTIONS+=(-DJAVA_HOME=$JAVA_HOME) fi OPTIONS+=(-DCMAKE_INSTALL_PREFIX=/usr) OPTIONS+=(-DJAVA_LIB_INSTALL_DIR=$JAVA_LIB_DIR ) OPTIONS+=(-DJSS_LIB_INSTALL_DIR=$JSS_LIB_DIR) if [ "$WITHOUT_JAVADOC" = true ] ; then OPTIONS+=(-DWITH_JAVADOC=FALSE) fi OPTIONS+=(-S $SRC_DIR) OPTIONS+=(-B .) cmake "${OPTIONS[@]}" OPTIONS=() if [ "$VERBOSE" = true ] ; then OPTIONS+=(VERBOSE=1) fi OPTIONS+=(CMAKE_NO_VERBOSE=1) OPTIONS+=(--no-print-directory) make "${OPTIONS[@]}" all if [ "$WITHOUT_JAVADOC" != true ] ; then make "${OPTIONS[@]}" javadoc fi if [ "$WITHOUT_TEST" != true ] ; then ctest --output-on-failure fi echo echo "Build artifacts:" echo "- Java archive: $WORK_DIR/jss.jar" echo "- shared library: $WORK_DIR/libjss.so" echo "- documentation: $WORK_DIR/docs" echo echo "To install the build: $0 install" echo "To create RPM packages: $0 rpm" echo exit fi if [ "$BUILD_TARGET" = "install" ] ; then if [ "$VERBOSE" = true ] ; then echo "Installing $NAME" fi OPTIONS=() if [ "$VERBOSE" = true ] ; then OPTIONS+=(VERBOSE=1) fi OPTIONS+=(CMAKE_NO_VERBOSE=1) OPTIONS+=(DESTDIR=$INSTALL_DIR) OPTIONS+=(INSTALL="install -p") OPTIONS+=(--no-print-directory) make "${OPTIONS[@]}" install exit fi ################################################################################ # Prepare RPM build ################################################################################ if [ "$SPEC_TEMPLATE" = "" ] ; then SPEC_TEMPLATE="$SRC_DIR/$NAME.spec" fi if [ "$VERSION" = "" ] ; then # if version not specified, get from spec template VERSION="$(rpmspec -P "$SPEC_TEMPLATE" | grep "^Version:" | awk '{print $2;}')" fi if [ "$DEBUG" = true ] ; then echo "VERSION: $VERSION" fi if [ "$RELEASE" = "" ] ; then # if release not specified, get from spec template RELEASE="$(rpmspec -P "$SPEC_TEMPLATE" --undefine dist | grep "^Release:" | awk '{print $2;}')" fi if [ "$DEBUG" = true ] ; then echo "RELEASE: $RELEASE" fi spec=$(<"$SPEC_TEMPLATE") regex=$'%global *_phase *([^\n]+)' if [[ $spec =~ $regex ]] ; then _PHASE="${BASH_REMATCH[1]}" fi if [ "$DEBUG" = true ] ; then echo "PHASE: ${_PHASE}" fi if [ "$WITH_TIMESTAMP" = true ] ; then TIMESTAMP="$(date -u +"%Y%m%d%H%M%S%Z")" _TIMESTAMP=".$TIMESTAMP" fi if [ "$DEBUG" = true ] ; then echo "TIMESTAMP: $TIMESTAMP" fi if [ "$WITH_COMMIT_ID" = true ]; then COMMIT_ID="$(git -C "$SRC_DIR" rev-parse --short=8 HEAD)" _COMMIT_ID=".$COMMIT_ID" fi if [ "$DEBUG" = true ] ; then echo "COMMIT_ID: $COMMIT_ID" fi echo "Building $NAME-$VERSION-$RELEASE${_TIMESTAMP}${_COMMIT_ID}" rm -rf BUILD rm -rf RPMS rm -rf SOURCES rm -rf SPECS rm -rf SRPMS mkdir BUILD mkdir RPMS mkdir SOURCES mkdir SPECS mkdir SRPMS ################################################################################ # Generate RPM sources ################################################################################ generate_rpm_sources echo "RPM sources:" find "$WORK_DIR/SOURCES" -type f -printf " %p\\n" if [ "$BUILD_TARGET" = "src" ] ; then exit fi ################################################################################ # Generate RPM spec ################################################################################ generate_rpm_spec echo "RPM spec:" find "$WORK_DIR/SPECS" -type f -printf " %p\\n" if [ "$BUILD_TARGET" = "spec" ] ; then exit fi ################################################################################ # Build source package ################################################################################ OPTIONS=() OPTIONS+=(--quiet) OPTIONS+=(--define "_topdir ${WORK_DIR}") if [ "$WITH_TIMESTAMP" = true ] ; then OPTIONS+=(--define "_timestamp ${_TIMESTAMP}") fi if [ "$WITH_COMMIT_ID" = true ] ; then OPTIONS+=(--define "_commit_id ${_COMMIT_ID}") fi if [ "$DIST" != "" ] ; then OPTIONS+=(--define "dist .$DIST") fi if [ "$DEBUG" = true ] ; then echo rpmbuild -bs "${OPTIONS[@]}" "$WORK_DIR/SPECS/$RPM_SPEC" fi # build SRPM with user-provided options rpmbuild -bs "${OPTIONS[@]}" "$WORK_DIR/SPECS/$RPM_SPEC" rc=$? if [ $rc != 0 ]; then echo "ERROR: Unable to build SRPM package" exit 1 fi SRPM="$(find "$WORK_DIR/SRPMS" -type f)" echo "SRPM package:" echo " $SRPM" if [ "$BUILD_TARGET" = "srpm" ] ; then exit fi ################################################################################ # Build binary packages ################################################################################ OPTIONS=() if [ "$VERBOSE" = true ] ; then OPTIONS+=(--define "_verbose 1") fi OPTIONS+=(--define "_topdir ${WORK_DIR}") if [ "$DEBUG" = true ] ; then echo rpmbuild --rebuild "${OPTIONS[@]}" "$SRPM" fi # rebuild RPM with hard-coded options in SRPM rpmbuild --rebuild "${OPTIONS[@]}" "$SRPM" rc=$? if [ $rc != 0 ]; then echo "ERROR: Unable to build RPM packages" exit 1 fi # install SRPM to restore sources and spec file removed during rebuild rpm -i --define "_topdir $WORK_DIR" "$SRPM" # flatten folder find "$WORK_DIR/RPMS" -mindepth 2 -type f -exec mv -i '{}' "$WORK_DIR/RPMS" ';' # remove empty subfolders find "$WORK_DIR/RPMS" -mindepth 1 -type d -delete echo "RPM packages:" find "$WORK_DIR/RPMS" -type f -printf " %p\\n" jss-5.0.0/build/000077500000000000000000000000001412550063600134145ustar00rootroot00000000000000jss-5.0.0/build/.gitkeep000066400000000000000000000000001412550063600150330ustar00rootroot00000000000000jss-5.0.0/cmake/000077500000000000000000000000001412550063600133755ustar00rootroot00000000000000jss-5.0.0/cmake/FindNSPR.cmake000066400000000000000000000056741412550063600157760ustar00rootroot00000000000000# - Try to find NSPR # Once done this will define # # NSPR_FOUND - system has NSPR # NSPR_INCLUDE_DIRS - the NSPR include directory # NSPR_LIBRARIES - Link these to use NSPR # NSPR_DEFINITIONS - Compiler switches required for using NSPR # # Copyright (c) 2010 Andreas Schneider # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # if (SANDBOX) # Bypass the cache: we want to use files from the directory above. set(NSS_FOUND TRUE) # Read the internal build directory from the dist directory set(DIST_DIR "${CMAKE_SOURCE_DIR}/../dist") file(READ "${DIST_DIR}/latest" LATEST_BUILD) string(STRIP "${LATEST_BUILD}" LATEST_BUILD) message(STATUS "NSS sandbox build directory: ${LATEST_BUILD}") # Directly set the NSS include and library directories set(NSPR_INCLUDE_DIRS "${DIST_DIR}/${LATEST_BUILD}/include/nspr") set(NSPR_LIBRARIES "${DIST_DIR}/${LATEST_BUILD}/lib") list(APPEND JSS_LD_FLAGS "-L${DIST_DIR}/${LATEST_BUILD}/lib") list(APPEND JSS_LD_FLAGS "-Wl,-rpath,${DIST_DIR}/${LATEST_BUILD}/lib") elseif (NSPR_LIBRARIES AND NSPR_INCLUDE_DIRS) # in cache already set(NSPR_FOUND TRUE) else (NSPR_LIBRARIES AND NSPR_INCLUDE_DIRS) find_package(PkgConfig) if (PKG_CONFIG_FOUND) pkg_check_modules(_NSPR nspr) endif (PKG_CONFIG_FOUND) find_path(NSPR_INCLUDE_DIR NAMES nspr.h PATHS ${_NSPR_INCLUDEDIR} /usr/include /usr/local/include /opt/local/include /sw/include PATH_SUFFIXES nspr4 nspr ) find_library(PLDS4_LIBRARY NAMES plds4 PATHS ${_NSPR_LIBDIR} /usr/lib /usr/local/lib /opt/local/lib /sw/lib ) find_library(PLC4_LIBRARY NAMES plc4 PATHS ${_NSPR_LIBDIR} /usr/lib /usr/local/lib /opt/local/lib /sw/lib ) find_library(NSPR4_LIBRARY NAMES nspr4 PATHS ${_NSPR_LIBDIR} /usr/lib /usr/local/lib /opt/local/lib /sw/lib ) set(NSPR_INCLUDE_DIRS ${NSPR_INCLUDE_DIR} ) if(PLDS4_LIBRARY) get_filename_component(PLDS4_LIBRARY "${PLDS4_LIBRARY}" DIRECTORY) set(NSPR_LIBRARIES ${NSPR_LIBRARIES} ${PLDS4_LIBRARY} ) endif() if(PLC4_LIBRARY) get_filename_component(PLC4_LIBRARY "${PLC4_LIBRARY}" DIRECTORY) set(NSPR_LIBRARIES ${NSPR_LIBRARIES} ${PLC4_LIBRARY} ) endif() if(NSPR4_LIBRARY) get_filename_component(NSPR4_LIBRARY "${NSPR4_LIBRARY}" DIRECTORY) set(NSPR_LIBRARIES ${NSPR_LIBRARIES} ${NSPR4_LIBRARY} ) endif() list(REMOVE_DUPLICATES NSPR_LIBRARIES) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(NSPR DEFAULT_MSG NSPR_LIBRARIES NSPR_INCLUDE_DIRS) # show the NSPR_INCLUDE_DIRS and NSPR_LIBRARIES variables only in the advanced view mark_as_advanced(NSPR_INCLUDE_DIRS NSPR_LIBRARIES) endif() jss-5.0.0/cmake/FindNSS.cmake000066400000000000000000000063441412550063600156520ustar00rootroot00000000000000# - Try to find NSS # Once done this will define # # NSS_FOUND - system has NSS # NSS_INCLUDE_DIRS - the NSS include directory # NSS_LIBRARIES - Link these to use NSS # NSS_DEFINITIONS - Compiler switches required for using NSS # # Copyright (c) 2010 Andreas Schneider # # Redistribution and use is allowed according to the terms of the New # BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. # if (SANDBOX) # Bypass the cache: we want to use files from the directory above. set(NSS_FOUND TRUE) # Read the internal build directory from the dist directory set(DIST_DIR "${CMAKE_SOURCE_DIR}/../dist") file(READ "${DIST_DIR}/latest" LATEST_BUILD) string(STRIP "${LATEST_BUILD}" LATEST_BUILD) message(STATUS "NSS sandbox build directory: ${LATEST_BUILD}") # Directly set the NSS include and library directories set(NSS_INCLUDE_DIRS "${DIST_DIR}/public/nss") set(NSS_LIBRARIES "${DIST_DIR}/${LATEST_BUILD}/lib") list(APPEND JSS_LD_FLAGS "-L${DIST_DIR}/${LATEST_BUILD}/lib") list(APPEND JSS_LD_FLAGS "-Wl,-rpath,${DIST_DIR}/${LATEST_BUILD}/lib") elseif (NSS_LIBRARIES AND NSS_INCLUDE_DIRS) # in cache already set(NSS_FOUND TRUE) else (NSS_LIBRARIES AND NSS_INCLUDE_DIRS) find_package(PkgConfig) if (PKG_CONFIG_FOUND) pkg_check_modules(_NSS nss) endif (PKG_CONFIG_FOUND) find_path(NSS_INCLUDE_DIR NAMES nss.h PATHS ${_NSS_INCLUDEDIR} /usr/include /usr/local/include /opt/local/include /sw/include PATH_SUFFIXES nss3 nss ) find_library(SSL3_LIBRARY NAMES ssl3 PATHS ${_NSS_LIBDIR} /usr/lib /usr/local/lib /opt/local/lib /sw/lib ) find_library(SMIME3_LIBRARY NAMES smime3 PATHS ${_NSS_LIBDIR} /usr/lib /usr/local/lib /opt/local/lib /sw/lib ) find_library(NSS3_LIBRARY NAMES nss3 PATHS ${_NSS_LIBDIR} /usr/lib /usr/local/lib /opt/local/lib /sw/lib ) find_library(NSSUTIL3_LIBRARY NAMES nssutil3 PATHS ${_NSS_LIBDIR} /usr/lib /usr/local/lib /opt/local/lib /sw/lib ) set(NSS_INCLUDE_DIRS ${NSS_INCLUDE_DIR} ) if(SSL3_LIBRARY) get_filename_component(SSL3_LIBRARY "${SSL3_LIBRARY}" DIRECTORY) set(NSS_LIBRARIES ${NSS_LIBRARIES} ${SSL3_LIBRARY} ) endif() if(SMIME3_LIBRARY) get_filename_component(SMIME3_LIBRARY "${SMIME3_LIBRARY}" DIRECTORY) set(NSS_LIBRARIES ${NSS_LIBRARIES} ${SMIME3_LIBRARY} ) endif() if(NSS3_LIBRARY) get_filename_component(NSS3_LIBRARY "${NSS3_LIBRARY}" DIRECTORY) set(NSS_LIBRARIES ${NSS_LIBRARIES} ${NSS3_LIBRARY} ) endif() if(NSSUTIL3_LIBRARY) get_filename_component(NSSUTIL3_LIBRARY "${NSSUTIL3_LIBRARY}" DIRECTORY) set(NSS_LIBRARIES ${NSS_LIBRARIES} ${NSSUTIL3_LIBRARY} ) endif() list(REMOVE_DUPLICATES NSS_LIBRARIES) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(NSS DEFAULT_MSG NSS_LIBRARIES NSS_INCLUDE_DIRS) # show the NSS_INCLUDE_DIRS and NSS_LIBRARIES variables only in the advanced view mark_as_advanced(NSS_INCLUDE_DIRS NSS_LIBRARIES) endif() jss-5.0.0/cmake/JSSCommon.cmake000066400000000000000000000220701412550063600162100ustar00rootroot00000000000000# Core of JSS building # Build JSS; high level flow macro(jss_build) # "set(..)" in CMake defines a globally-scoped variable (or more # precisely, a variable that exists in all scopes _after_ this one) # by default. These are three helpful globs of files for dependencies: # all java, headers, and c source files. Note that src/main/java/*.java differs # from the bash-style glob in that it matches all files which begin with # "src/main/java/" and end with ".java". This includes, e.g., # "src/main/java/org/mozilla/jss/CryptoManager.java". Because these globs are computed # at cmake time (prior to the make step) incremental builds are not # possible; each time the build directory should be removed and recreated # prior to building again. jss_build_globs() # To build JSS, we need: # 1. To build the Java files. # 2. To copy the headers for compilation. # 3. To build the library. # 4. To build the jar. # 5. To build the javadocs. jss_build_java() jss_build_includes() jss_build_c() jss_build_jars() jss_build_javadocs() endmacro() macro(jss_build_globs) file(GLOB_RECURSE JAVA_SOURCES src/main/java/*.java) file(GLOB_RECURSE JAVA_TEST_SOURCES src/test/java/*.java) # Write the Java sources to a file to reduce the size of the javac # command line. list(SORT JAVA_SOURCES) list(SORT JAVA_TEST_SOURCES) jss_list_join(JAVA_SOURCES "\n" JAVA_SOURCES_CONTENTS) jss_list_join(JAVA_TEST_SOURCES "\n" JAVA_TEST_SOURCES_CONTENTS) file(WRITE "${JAVA_SOURCES_FILE}" "${JAVA_SOURCES_CONTENTS}") file(WRITE "${JAVA_TEST_SOURCES_FILE}" "${JAVA_TEST_SOURCES_CONTENTS}") file(GLOB_RECURSE _C_HEADERS src/main/java/*.h) foreach(_C_HEADER ${_C_HEADERS}) if(${_C_HEADER} MATCHES "mozilla/jss/tests/") list(APPEND C_TEST_HEADERS "${_C_HEADER}") else() list(APPEND C_HEADERS "${_C_HEADER}") endif() endforeach() # We exclude any C files in the tests directory because they shouldn't # contribute to our library. They should instead be built as part of the # test suite and probably be built as stand alone binaries which link # against libjss.so (at most). file(GLOB_RECURSE C_SOURCES src/main/java/*.c) file(GLOB_RECURSE C_TEST_SOURCES src/test/java/*.c) endmacro() # Build all Java sources into classes and generate JNI headers macro(jss_build_java) # Create a fake, pseudo-target for generate_java -- we have to have some # status for when the build finishes for the add_custom_target to depend # on, but it also must be the last-thing created; thus, we touch # ${JNI_OUTPUTS} after the javac command finishes. set(JNI_OUTPUTS "${TARGETS_OUTPUT_DIR}/finished_generate_java") set(TESTS_JNI_OUTPUTS "${TARGETS_OUTPUT_DIR}/finished_tests_generate_java") # We frequently use the add_custom_command + add_custom_target wrapper due # to a quirk of CMake. This is documented more extensively in the # following links: # https://samthursfield.wordpress.com/2015/11/21/cmake-dependencies-between-targets-and-files-and-custom-commands/ # https://gitlab.kitware.com/cmake/community/wikis/FAQ#how-can-i-add-a-dependency-to-a-source-file-which-is-generated-in-a-subdirectory add_custom_command( OUTPUT "${JNI_OUTPUTS}" COMMAND ${Java_JAVAC_EXECUTABLE} ${JSS_JAVAC_FLAGS} -d ${CLASSES_OUTPUT_DIR} -h ${JNI_OUTPUT_DIR} @${JAVA_SOURCES_FILE} COMMAND touch "${JNI_OUTPUTS}" DEPENDS ${JAVA_SOURCES} ) add_custom_command( OUTPUT "${TESTS_JNI_OUTPUTS}" COMMAND ${Java_JAVAC_EXECUTABLE} ${JSS_TEST_JAVAC_FLAGS} -d ${TESTS_CLASSES_OUTPUT_DIR} -h ${TESTS_JNI_OUTPUT_DIR} @${JAVA_TEST_SOURCES_FILE} COMMAND touch "${TESTS_JNI_OUTPUTS}" DEPENDS ${JAVA_TEST_SOURCES} ) add_custom_target( generate_java ALL DEPENDS ${JNI_OUTPUTS} ${TESTS_JNI_OUTPUTS} ) endmacro() # "Build" all includes by copying them to a common directory macro(jss_build_includes) # Note that file(COPY ...) operations are performed at "CMake" run time, # (equivalent to configure time), so CMake needs to be reconfigured every # time a new header file is added. This is most easily done by removing # the build directory and recreating it. This also applies to all other # build steps as the globs are computed at configure time as well. foreach(C_HEADER ${C_HEADERS}) file(COPY "${C_HEADER}" DESTINATION ${INCLUDE_OUTPUT_DIR}) endforeach() foreach(C_TEST_HEADER ${C_TEST_HEADERS}) file(COPY "${C_TEST_HEADER}" DESTINATION ${TESTS_INCLUDE_OUTPUT_DIR}) endforeach() add_custom_target( generate_includes ) endmacro() # Compile a single C file macro(jss_build_c_file C_FILE C_OUTPUT C_TARGET C_DIR) # C files can be built in parallel. This macro builds each file wrapped in # add_custom_command+add_custom_target so parallel builds work. Note that # each build depends on generate_java and generate_includes to have # finished, else many headers wouldn't exist. add_custom_command( OUTPUT "${C_OUTPUT}" COMMAND ${CMAKE_C_COMPILER} -fPIC ${JSS_C_FLAGS} -o ${C_OUTPUT} -c ${C_FILE} WORKING_DIRECTORY ${C_DIR} DEPENDS ${C_FILE} DEPENDS generate_java DEPENDS generate_includes ) add_custom_target( "generate_c_${C_TARGET}" DEPENDS "${C_OUTPUT}" ${C_HEADERS} ) endmacro() # Compile all C source files and build libjss library macro(jss_build_c) foreach(C_SOURCE ${C_SOURCES}) get_filename_component(C_TARGET ${C_SOURCE} NAME_WE) get_filename_component(C_DIR ${C_SOURCE} DIRECTORY) set(C_OUTPUT "${LIB_OUTPUT_DIR}/${C_TARGET}.o") jss_build_c_file("${C_SOURCE}" "${C_OUTPUT}" "${C_TARGET}" "${C_DIR}") list(APPEND C_OUTPUTS "${C_OUTPUT}") endforeach() # Combine all C targets here into a single pseudo-target for parallel # builds. add_custom_target( generate_c ALL DEPENDS ${C_OUTPUTS} ) # We generate two libraries: build/lib/libjss.so and build/libjss.so: # the former is for testing and is unversioned, so all symbols are public # and can thus be tested; the latter is for releases and is versioned, # limiting which symbols are made public. We only need to make the JNI # symbols public as libjss.so should only be used from Java in conjunction # with jss.jar. add_custom_command( OUTPUT "${JSS_SO_PATH}" "${JSS_TESTS_SO_PATH}" COMMAND ${CMAKE_C_COMPILER} -o ${JSS_TESTS_SO_PATH} ${LIB_OUTPUT_DIR}/*.o ${JSS_LD_FLAGS} ${JSS_LIBRARY_FLAGS} COMMAND ${CMAKE_C_COMPILER} -o ${JSS_SO_PATH} ${LIB_OUTPUT_DIR}/*.o ${JSS_LD_FLAGS} ${JSS_VERSION_SCRIPT} ${JSS_LIBRARY_FLAGS} DEPENDS generate_c ) # Add a target for anything depending on the library existing. add_custom_target( generate_so ALL DEPENDS ${JSS_SO_PATH} ${JSS_TESTS_SO_PATH} ) endmacro() # Build the jar by combining the java classes from generate_java step macro(jss_build_jars) # Note that build/MANIFEST.MF is generated by JSSConfig.cmake's # jss_config_version macro. Further, this doesn't yet build a reproducible # JAR. add_custom_command( OUTPUT "${JSS_BUILD_JAR_PATH}" COMMAND "${Java_JAR_EXECUTABLE}" cmf "${CMAKE_BINARY_DIR}/MANIFEST.MF" "${JSS_BUILD_JAR_PATH}" -C "${CLASSES_OUTPUT_DIR}" org -C "${CLASSES_OUTPUT_DIR}" META-INF DEPENDS generate_java ) add_custom_command( OUTPUT "${JSS_TESTS_JAR_PATH}" COMMAND "${Java_JAR_EXECUTABLE}" cmf "${CMAKE_BINARY_DIR}/MANIFEST.MF" ${JSS_TESTS_JAR_PATH} -C "${TESTS_CLASSES_OUTPUT_DIR}" org DEPENDS generate_java ) add_custom_target( generate_build_jar DEPENDS "${JSS_BUILD_JAR_PATH}" ) add_custom_command( OUTPUT "${JSS_JAR_PATH}" COMMAND "${PROJECT_SOURCE_DIR}/tools/reproducible_jar.sh" "${JSS_BUILD_JAR_PATH}" "${REPRODUCIBLE_TEMP_DIR}" "${JSS_JAR_PATH}" DEPENDS generate_build_jar ) add_custom_target( generate_jar ALL DEPENDS "${JSS_JAR_PATH}" "${JSS_TESTS_JAR_PATH}" ) endmacro() # Build javadocs from the source files macro(jss_build_javadocs) # Add another pseudo-target here as well -- javadocs create a lot of # output, but anything which depends on the javadocs existing should # depend on the javadoc target. set(JAVADOCS_OUTPUTS "${TARGETS_OUTPUT_DIR}/finished_generate_javadocs") add_custom_command( OUTPUT ${JAVADOCS_OUTPUTS} COMMAND "${Java_JAVADOC_EXECUTABLE}" -overview "${PROJECT_SOURCE_DIR}/tools/javadoc/overview.html" -windowtitle "${JSS_WINDOW_TITLE}" -notimestamp -breakiterator -classpath ${JAVAC_CLASSPATH} -sourcepath ${PROJECT_SOURCE_DIR} -d ${DOCS_OUTPUT_DIR} @${JAVA_SOURCES_FILE} COMMAND touch "${JAVADOCS_OUTPUTS}" DEPENDS ${JAVA_SOURCES} ) add_custom_target( javadoc DEPENDS ${JAVADOCS_OUTPUTS} ) # For compliance with GNU Make standard targets add_custom_target( html DEPENDS javadoc ) endmacro() jss-5.0.0/cmake/JSSConfig.cmake000066400000000000000000000436051412550063600161740ustar00rootroot00000000000000macro(jss_config) # Set the current JSS release number. Arguments are: # MAJOR MINOR PATCH BETA # When BETA is 1, it is a pre-release (it enables some tests). # When BETA is 0, it is a final release. jss_config_version(5 0 0 0) # Configure output directories jss_config_outputs() # Configure flags for compiling and linking jss_config_cflags() jss_config_ldflags() # Configure java-related flags jss_config_java() # Configure test variables jss_config_tests() # Check symbols to see what tests we run jss_config_symbols() # Template auto-generated files jss_config_template() endmacro() macro(jss_config_version MAJOR MINOR PATCH BETA) # This sets the JSS Version for use in CMake and propagates it to the # necessary source locations. These are: # # src/main/java/org/mozilla/jss/util/jssver.h{.in,} # lib/MANIFEST.MF.in -> build/MANIFEST.MF # # On a build, these automatically get generated with the correct versions # included. Note that all "sets" are of global scope, so these variables # can be used anywhere that is necessary. Some uses are for setting the # version number in the library and jar file, etc. # Define variables from passed arguments set(JSS_VERSION_MAJOR "${MAJOR}") set(JSS_VERSION_MINOR "${MINOR}") set(JSS_VERSION_PATCH "${PATCH}") set(JSS_VERSION_BETA "${BETA}") set(JSS_VERSION "${JSS_VERSION_MAJOR}.${JSS_VERSION_MINOR}.${JSS_VERSION_PATCH}") set(JSS_VERSION_MANIFEST "${JSS_VERSION_MAJOR}.${JSS_VERSION_MINOR}") set(JSS_VERSION_STR "JSS_${JSS_VERSION_MAJOR}_${JSS_VERSION_MINOR}") if(${PATCH} GREATER 0) set(JSS_VERSION_MANIFEST "${JSS_VERSION_MANIFEST}.${JSS_VERSION_PATCH}") set(JSS_VERSION_STR "${JSS_VERSION_STR}_${JSS_VERSION_PATCH}") endif() if(${BETA} GREATER 0) set(JSS_VERSION "${JSS_VERSION} beta ${JSS_VERSION_BETA}") set(JSS_VERSION_STR "${JSS_VERSION_STR}_b${JSS_VERSION_BETA}") endif() endmacro() macro(jss_config_outputs) # Global variables representing various output files; note that these # directories are created at the end of this macro. set(CLASSES_OUTPUT_DIR "${CMAKE_BINARY_DIR}/classes/jss") set(CONFIG_OUTPUT_DIR "${CMAKE_BINARY_DIR}/config") set(DOCS_OUTPUT_DIR "${CMAKE_BINARY_DIR}/docs") set(LIB_OUTPUT_DIR "${CMAKE_BINARY_DIR}/lib") set(BIN_OUTPUT_DIR "${CMAKE_BINARY_DIR}/bin") set(INCLUDE_OUTPUT_DIR "${CMAKE_BINARY_DIR}/include/jss") set(JNI_OUTPUT_DIR "${CMAKE_BINARY_DIR}/include/jss/_jni") if (NOT DEFINED JAVA_LIB_INSTALL_DIR) set(JAVA_LIB_INSTALL_DIR "/usr/lib/java") endif(NOT DEFINED JAVA_LIB_INSTALL_DIR) if (NOT DEFINED JSS_LIB_INSTALL_DIR) set(JSS_LIB_INSTALL_DIR "/usr/lib/jss") endif(NOT DEFINED JSS_LIB_INSTALL_DIR) # This folder is for pseudo-locations for CMake targets set(TARGETS_OUTPUT_DIR "${CMAKE_BINARY_DIR}/.targets") set(JAVA_SOURCES_FILE "${TARGETS_OUTPUT_DIR}/java.sources") set(JAVA_TEST_SOURCES_FILE "${TARGETS_OUTPUT_DIR}/java-test.sources") # These folders are for the NSS DBs created during testing set(RESULTS_DATA_OUTPUT_DIR "${CMAKE_BINARY_DIR}/results/data") set(RESULTS_NSSDB_OUTPUT_DIR "${CMAKE_BINARY_DIR}/results/nssdb") set(RESULTS_NSSDB_FIPS_OUTPUT_DIR "${CMAKE_BINARY_DIR}/results/fips") set(RESULTS_NSSDB_INTERNET_OUTPUT_DIR "${CMAKE_BINARY_DIR}/results/internet") # This is a temporary location for building the reproducible jar set(REPRODUCIBLE_TEMP_DIR "${CMAKE_BINARY_DIR}/reproducible") set(JSS_BUILD_JAR "staging.jar") set(JSS_JAR "jss.jar") set(JSS_SO "libjss.so") set(JSS_BUILD_JAR_PATH "${CMAKE_BINARY_DIR}/${JSS_BUILD_JAR}") set(JSS_JAR_PATH "${CMAKE_BINARY_DIR}/${JSS_JAR}") set(JSS_SO_PATH "${CMAKE_BINARY_DIR}/${JSS_SO}") # These options are for the test suite and mirror their non-tests # counterparts. Note that JSS_TESTS_SO is the same as JSS_SO, but # JSS_TESTS_SO_PATH differs -- one is "unversioned" and lacks a # version script so we can test internal methods. set(TESTS_CLASSES_OUTPUT_DIR "${CMAKE_BINARY_DIR}/classes/tests") set(TESTS_INCLUDE_OUTPUT_DIR "${CMAKE_BINARY_DIR}/include/tests") set(TESTS_JNI_OUTPUT_DIR "${CMAKE_BINARY_DIR}/include/jss/_jni") set(JSS_TESTS_JAR "tests-jss.jar") set(JSS_TESTS_SO "${JSS_SO}") set(JSS_TESTS_JAR_PATH "${CMAKE_BINARY_DIR}/${JSS_TESTS_JAR}") set(JSS_TESTS_SO_PATH "${LIB_OUTPUT_DIR}/${JSS_TESTS_SO}") # Create the *_OUTPUT_DIR locations. file(MAKE_DIRECTORY "${CLASSES_OUTPUT_DIR}") file(MAKE_DIRECTORY "${CONFIG_OUTPUT_DIR}") file(MAKE_DIRECTORY "${DOCS_OUTPUT_DIR}") file(MAKE_DIRECTORY "${LIB_OUTPUT_DIR}") file(MAKE_DIRECTORY "${BIN_OUTPUT_DIR}") file(MAKE_DIRECTORY "${INCLUDE_OUTPUT_DIR}") file(MAKE_DIRECTORY "${JNI_OUTPUT_DIR}") file(MAKE_DIRECTORY "${TARGETS_OUTPUT_DIR}") file(MAKE_DIRECTORY "${TESTS_CLASSES_OUTPUT_DIR}") file(MAKE_DIRECTORY "${TESTS_INCLUDE_OUTPUT_DIR}") file(MAKE_DIRECTORY "${TESTS_JNI_OUTPUT_DIR}") endmacro() macro(jss_config_cflags) # We check that the C compiler can handle each of the C flags below include(CheckCCompilerFlag) # This list of C flags was taken from the original build scripts for # debug and release builds. if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") list(APPEND JSS_RAW_C_FLAGS "-Og") list(APPEND JSS_RAW_C_FLAGS "-ggdb") list(APPEND JSS_RAW_C_FLAGS "-DDEBUG") list(APPEND JSS_RAW_C_FLAGS "-DFORCE_PR_ASSERT") else() list(APPEND JSS_RAW_C_FLAGS "-O2") endif() list(APPEND JSS_RAW_C_FLAGS "-Wall") list(APPEND JSS_RAW_C_FLAGS "-std=gnu99") list(APPEND JSS_RAW_C_FLAGS "-Wno-cast-function-type") list(APPEND JSS_RAW_C_FLAGS "-Wno-unused-parameter") list(APPEND JSS_RAW_C_FLAGS "-Wno-unknown-warning-option") list(APPEND JSS_RAW_C_FLAGS "-Wno-unused-but-set-variable") list(APPEND JSS_RAW_C_FLAGS "-Werror-implicit-function-declaration") list(APPEND JSS_RAW_C_FLAGS "-Wno-switch") list(APPEND JSS_RAW_C_FLAGS "-I${INCLUDE_OUTPUT_DIR}") foreach(JNI_INCLUDE_DIR ${JNI_INCLUDE_DIRS}) list(APPEND JSS_RAW_C_FLAGS "-I${JNI_INCLUDE_DIR}") endforeach() foreach(NSPR_INCLUDE_DIR ${NSPR_INCLUDE_DIRS}) list(APPEND JSS_RAW_C_FLAGS "-I${NSPR_INCLUDE_DIR}") endforeach() foreach(NSS_INCLUDE_DIR ${NSS_INCLUDE_DIRS}) list(APPEND JSS_RAW_C_FLAGS "-I${NSS_INCLUDE_DIR}") endforeach() foreach(NSPR_LIBRARY ${NSPR_LIBRARIES}) list(APPEND JSS_RAW_C_FLAGS "-L${NSPR_LIBRARY}") endforeach() foreach(NSS_LIBRARY ${NSS_LIBRARIES}) list(APPEND JSS_RAW_C_FLAGS "-L${NSS_LIBRARY}") endforeach() foreach(JSS_RAW_C_FLAG ${JSS_RAW_C_FLAGS}) # Validate that each of our desired CFLAGS is supported by the # compiler, or well, at least the compiler doesn't immediately # error on it. :) check_c_compiler_flag(${JSS_RAW_C_FLAG} HAVE_C_FLAG) if(${HAVE_C_FLAG}) list(APPEND JSS_C_FLAGS "${JSS_RAW_C_FLAG}") endif() endforeach() # Handle passed-in C flags as well; assume they are valid. separate_arguments(PASSED_C_FLAGS UNIX_COMMAND "${CMAKE_C_FLAGS}") foreach(PASSED_C_FLAG ${PASSED_C_FLAGS}) list(INSERT JSS_C_FLAGS 0 "${PASSED_C_FLAG}") endforeach() message(STATUS "JSS C FLAGS: ${JSS_C_FLAGS}") endmacro() macro(jss_config_ldflags) # This list of C linker flags was taken from the original build scripts # for debug and release builds. We lack a "check_c_linker_flag" macro, # so no effort is made to validate these flags. list(APPEND JSS_LD_FLAGS "-lsmime3") list(APPEND JSS_LD_FLAGS "-lssl3") list(APPEND JSS_LD_FLAGS "-lnss3") list(APPEND JSS_LD_FLAGS "-lnssutil3") list(APPEND JSS_LD_FLAGS "-lplc4") list(APPEND JSS_LD_FLAGS "-lplds4") list(APPEND JSS_LD_FLAGS "-lnspr4") list(APPEND JSS_LD_FLAGS "-lpthread") list(APPEND JSS_LD_FLAGS "-ldl") separate_arguments(PASSED_LD_FLAGS UNIX_COMMAND "${CMAKE_SHARED_LINKER_FLAGS}") foreach(PASSED_LD_FLAG ${PASSED_LD_FLAGS}) list(INSERT JSS_LD_FLAGS 0 "${PASSED_LD_FLAG}") endforeach() # This set of flags is specific to building the libjss library. list(APPEND JSS_LIBRARY_FLAGS "-shared") list(APPEND JSS_LIBRARY_FLAGS "-Wl,-z,defs") list(APPEND JSS_LIBRARY_FLAGS "-Wl,-soname") list(APPEND JSS_LIBRARY_FLAGS "-Wl,${JSS_SO}") set(JSS_VERSION_SCRIPT "-Wl,--version-script,${PROJECT_SOURCE_DIR}/lib/jss.map") message(STATUS "JSS LD FLAGS: ${JSS_LD_FLAGS}") message(STATUS "JSS LIBRARY FLAGS: ${JSS_LIBRARY_FLAGS}") endmacro() macro(jss_config_java) # Find various JARs required by JSS build and test suite find_jar( SLF4J_API_JAR NAMES api slf4j/api slf4j-api ) find_jar( LANG_JAR NAMES apache-commons-lang3 commons-lang3 ) find_jar( SLF4J_JDK14_JAR NAMES jdk14 slf4j/jdk14 slf4j-jdk14 ) find_jar( JUNIT4_JAR NAMES junit4 junit ) find_jar( HAMCREST_JAR NAMES hamcrest/core hamcrest-core hamcrest/hamcrest ) # Validate that we've found the required JARs if(SLF4J_API_JAR STREQUAL "SLF4J_API_JAR-NOTFOUND") message(FATAL_ERROR "Required dependency sfl4j-api.jar not found by find_jar!") endif() if(LANG_JAR STREQUAL "LANG_JAR-NOTFOUND") message(FATAL_ERROR "Required dependency apache-commons-lang.jar not found by find_jar!") endif() if(SLF4J_JDK14_JAR STREQUAL "SLF4J_JDK14_JAR-NOTFOUND") message(WARNING "Test dependency sfl4j-jdk14.jar not found by find_jar! Tests might not run properly.") endif() if(JUNIT4_JAR STREQUAL "JUNIT4_JAR-NOTFOUND") message(FATAL_ERROR "Test dependency junit4.jar not found by find_jar! Tests will not compile.") endif() if(HAMCREST_JAR STREQUAL "HAMCREST_JAR-NOTFOUND") message(WARNING "Test dependency hamcrest/core.jar not found by find_jar! Tests might not run properly.") endif() # Set class paths set(JAVAC_CLASSPATH "${SLF4J_API_JAR}:${LANG_JAR}") set(TEST_CLASSPATH "${JSS_JAR_PATH}:${JSS_TESTS_JAR_PATH}:${JAVAC_CLASSPATH}:${SLF4J_JDK14_JAR}:${JUNIT4_JAR}:${HAMCREST_JAR}") message(STATUS "javac classpath: ${JAVAC_CLASSPATH}") message(STATUS "tests classpath: ${TEST_CLASSPATH}") # Set compile flags for JSS list(APPEND JSS_JAVAC_FLAGS "-classpath") list(APPEND JSS_JAVAC_FLAGS "${JAVAC_CLASSPATH}") list(APPEND JSS_JAVAC_FLAGS "-sourcepath") list(APPEND JSS_JAVAC_FLAGS "${PROJECT_SOURCE_DIR}/src/main/java") # Ensure we're compatible with JDK 8 list(APPEND JSS_JAVAC_FLAGS "-target") list(APPEND JSS_JAVAC_FLAGS "1.8") list(APPEND JSS_JAVAC_FLAGS "-source") list(APPEND JSS_JAVAC_FLAGS "1.8") # Handle passed-in javac flags as well; assume they are valid. separate_arguments(PASSED_JAVAC_FLAGS UNIX_COMMAND "$ENV{JAVACFLAGS}") foreach(PASSED_JAVAC_FLAG ${PASSED_JAVAC_FLAGS}) list(APPEND JSS_JAVAC_FLAGS "${PASSED_JAVAC_FLAG}") endforeach() if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") list(APPEND JSS_JAVAC_FLAGS "-g") list(APPEND JSS_JAVAC_FLAGS "-Xlint:unchecked") else() list(APPEND JSS_JAVAC_FLAGS "-O") endif() # Set compile flags for JSS test suite list(APPEND JSS_TEST_JAVAC_FLAGS "-classpath") list(APPEND JSS_TEST_JAVAC_FLAGS "${JAVAC_CLASSPATH}:${JUNIT4_JAR}:${CLASSES_OUTPUT_DIR}") list(APPEND JSS_TEST_JAVAC_FLAGS "-sourcepath") list(APPEND JSS_TEST_JAVAC_FLAGS "${PROJECT_SOURCE_DIR}/src/main/java") # Ensure we're compatible with JDK 8 list(APPEND JSS_TEST_JAVAC_FLAGS "-target") list(APPEND JSS_TEST_JAVAC_FLAGS "1.8") list(APPEND JSS_TEST_JAVAC_FLAGS "-source") list(APPEND JSS_TEST_JAVAC_FLAGS "1.8") # Handle passed-in javac flags as well; assume they are valid. separate_arguments(PASSED_JAVAC_FLAGS UNIX_COMMAND "$ENV{JAVACFLAGS}") foreach(PASSED_JAVAC_FLAG ${PASSED_JAVAC_FLAGS}) list(APPEND JSS_TEST_JAVAC_FLAGS "${PASSED_JAVAC_FLAG}") endforeach() if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug") list(APPEND JSS_TEST_JAVAC_FLAGS "-g") else() list(APPEND JSS_TEST_JAVAC_FLAGS "-O") endif() message(STATUS "JSS JAVAC FLAGS: ${JSS_JAVAC_FLAGS}") message(STATUS "JSS TEST JAVAC FLAGS: ${JSS_TEST_JAVAC_FLAGS}") # Variables for javadoc building. set(JSS_WINDOW_TITLE "JSS: Java Security Services") set(JSS_BASE_PORT 2876) math(EXPR JSS_TEST_PORT_CLIENTAUTH ${JSS_BASE_PORT}+0) math(EXPR JSS_TEST_PORT_CLIENTAUTH_FIPS ${JSS_BASE_PORT}+1) # Create META-INF directory for provider file(MAKE_DIRECTORY "${CLASSES_OUTPUT_DIR}/META-INF/services") endmacro() macro(jss_config_template) # Template files configure_file( "${PROJECT_SOURCE_DIR}/src/main/java/org/mozilla/jss/jssconfig.h.in" "${PROJECT_SOURCE_DIR}/src/main/java/org/mozilla/jss/jssconfig.h" ) configure_file( "${PROJECT_SOURCE_DIR}/src/main/java/org/mozilla/jss/util/jssver.h.in" "${PROJECT_SOURCE_DIR}/src/main/java/org/mozilla/jss/util/jssver.h" ) configure_file( "${PROJECT_SOURCE_DIR}/lib/MANIFEST.MF.in" "${CMAKE_BINARY_DIR}/MANIFEST.MF" ) configure_file( "${PROJECT_SOURCE_DIR}/lib/java.security.Provider.in" "${CLASSES_OUTPUT_DIR}/META-INF/services/java.security.Provider" ) configure_file( "${PROJECT_SOURCE_DIR}/tools/run_test.sh.in" "${CMAKE_BINARY_DIR}/run_test.sh" ) set(JSS_CFG_PATH "${CONFIG_OUTPUT_DIR}/jss.cfg") configure_file( "${PROJECT_SOURCE_DIR}/tools/java.security.in" "${CONFIG_OUTPUT_DIR}/java.security" @ONLY ) set(NSS_DB_PATH "${RESULTS_NSSDB_OUTPUT_DIR}") configure_file( "${PROJECT_SOURCE_DIR}/tools/jss.cfg.in" "${JSS_CFG_PATH}" ) set(JSS_CFG_PATH "${CONFIG_OUTPUT_DIR}/jss-fips.cfg") configure_file( "${PROJECT_SOURCE_DIR}/tools/java.security.in" "${CONFIG_OUTPUT_DIR}/fips.security" @ONLY ) set(NSS_DB_PATH "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}") configure_file( "${PROJECT_SOURCE_DIR}/tools/jss.cfg.in" "${JSS_CFG_PATH}" ) set(JSS_CFG_PATH "${CONFIG_OUTPUT_DIR}/jss-internet.cfg") configure_file( "${PROJECT_SOURCE_DIR}/tools/java.security.in" "${CONFIG_OUTPUT_DIR}/internet.security" @ONLY ) set(NSS_DB_PATH "${RESULTS_NSSDB_INTERNET_OUTPUT_DIR}") configure_file( "${PROJECT_SOURCE_DIR}/tools/jss.cfg.in" "${JSS_CFG_PATH}" ) unset(JSS_CFG_PATH) unset(NSS_DB_PATH) endmacro() macro(jss_config_symbols) list(APPEND CMAKE_REQUIRED_INCLUDES ${NSPR_INCLUDE_DIRS}) list(APPEND CMAKE_REQUIRED_INCLUDES ${NSS_INCLUDE_DIRS}) jss_list_join(JSS_C_FLAGS " " CMAKE_REQUIRED_FLAGS) check_symbol_exists("CKM_AES_CMAC" "nspr.h;nss.h;pkcs11t.h" HAVE_NSS_CMAC) if(NOT HAVE_NSS_CMAC) message(WARNING "Your NSS version doesn't support CMAC; some features of JSS won't work.") endif() check_symbol_exists("CKM_SP800_108_COUNTER_KDF" "nspr.h;nss.h;pkcs11t.h" HAVE_NSS_KBKDF) if(NOT HAVE_NSS_KBKDF) message(WARNING "Your NSS version doesn't support NIST SP800-108 KBKDF; some features of JSS won't work.") endif() try_compile(CK_HAVE_COMPILING_OAEP ${CMAKE_BINARY_DIR}/results ${CMAKE_SOURCE_DIR}/tools/tests/oaep.c CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${CMAKE_REQUIRED_INCLUDES}" "-DREQUIRED_FLAGS=${CMAKE_REQUIRED_FLAGS}" LINK_OPTIONS ${JSS_LD_FLAGS} OUTPUT_VARIABLE COMP_OUT) if (CK_HAVE_COMPILING_OAEP) set(HAVE_NSS_OAEP TRUE) else() message(WARNING "Your NSS version doesn't support RSA-OAEP key wra/unwrap; some features of JSS won't work.") message(WARNING "Compile output: ${COMP_OUT}") endif() if(HAVE_NSS_CMAC) try_run(CK_HAVE_WORKING_CMAC CK_HAVE_COMPILING_CMAC ${CMAKE_BINARY_DIR}/results ${CMAKE_SOURCE_DIR}/tools/tests/cmac.c CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${CMAKE_REQUIRED_INCLUDES}" "-DREQUIRED_FLAGS=${CMAKE_REQUIRED_FLAGS}" COMPILE_OUTPUT_VARIABLE COMP_OUT RUN_OUTPUT_VARIABLE RUN_OUT) if (NOT CK_HAVE_WORKING_CMAC STREQUAL "0" OR NOT CK_HAVE_COMPILING_CMAC) set(HAVE_NSS_CMAC FALSE) set(HAVE_NSS_KBKDF FALSE) message(WARNING "Your NSS version is broken: between NSS v3.47 and v3.50, the values of CKM_AES_CMAC and CKM_AES_CMAC_GENERAL were swapped. Disabling CMAC and KBKDF support.") message(WARNING "Compile output: ${COMP_OUT}") message(WARNING "Run output: ${RUN_OUT}") endif() endif() # Added in NSS v3.43 check_struct_has_member( SSLCipherSuiteInfo kdfHash ssl.h HAVE_NSS_CIPHER_SUITE_INFO_KDFHASH ) # Added in NSS v3.34 check_struct_has_member( SSLChannelInfo originalKeaGroup ssl.h HAVE_NSS_CHANNEL_INFO_ORIGINAL_KEA_GROUP ) # Added in NSS v3.45 check_struct_has_member( SSLChannelInfo peerDelegCred ssl.h HAVE_NSS_CHANNEL_INFO_PEER_DELEG_CRED ) # Added in NSS v3.43 check_struct_has_member( SSLPreliminaryChannelInfo zeroRttCipherSuite ssl.h HAVE_NSS_PRELIMINARY_CHANNEL_INFO_ZERO_RTT_CIPHER_SUITE ) # Added in NSS v3.48 check_struct_has_member( SSLPreliminaryChannelInfo peerDelegCred ssl.h HAVE_NSS_PRELIMINARY_CHANNEL_INFO_PEER_DELEG_CRED ) endmacro() macro(jss_config_tests) # Common variables used as arguments to several tests set(JSS_TEST_DIR "${PROJECT_SOURCE_DIR}/src/test/java/org/mozilla/jss/tests") set(PASSWORD_FILE "${JSS_TEST_DIR}/passwords") set(DB_PWD "m1oZilla") endmacro() jss-5.0.0/cmake/JSSTests.cmake000066400000000000000000000534361412550063600160740ustar00rootroot00000000000000macro(jss_tests) enable_testing() jss_tests_compile() # Create directories for test cases: # - results/data # - results/nssdb # - results/fips jss_test_exec( NAME "Clean_Data_Dir" COMMAND "cmake" "-E" "remove_directory" "${RESULTS_DATA_OUTPUT_DIR}" ) jss_test_exec( NAME "Create_Data_Dir" COMMAND "cmake" "-E" "make_directory" "${RESULTS_DATA_OUTPUT_DIR}" DEPENDS "Clean_Data_Dir" ) # Rather than creating our results directories earlier in JSSConfig, # create them here so that the test suite can be rerun multiple times. jss_test_exec( NAME "Clean_Setup_DBs" COMMAND "cmake" "-E" "remove_directory" "${RESULTS_NSSDB_OUTPUT_DIR}" ) jss_test_exec( NAME "Create_Setup_DBs" COMMAND "cmake" "-E" "make_directory" "${RESULTS_NSSDB_OUTPUT_DIR}" DEPENDS "Clean_Setup_DBs" ) jss_test_java( NAME "Setup_DBs" COMMAND "org.mozilla.jss.tests.SetupDBs" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "Create_Setup_DBs" MODE "NONE" ) # Various FIPS related tests depend on FIPS being enabled; since this # affects the entire NSS DB, create a separate database for them. jss_test_exec( NAME "Clean_FIPS_Setup_DBs" COMMAND "cmake" "-E" "remove_directory" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" ) jss_test_exec( NAME "Create_FIPS_Setup_DBs" COMMAND "cmake" "-E" "make_directory" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" DEPENDS "Clean_FIPS_Setup_DBs" ) jss_test_java( NAME "Setup_FIPS_DBs" COMMAND "org.mozilla.jss.tests.SetupDBs" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "Create_FIPS_Setup_DBs" MODE "NONE" ) # NSS DB for internet connected tests; imports global root CA certs. if(TEST_WITH_INTERNET) jss_test_exec( NAME "Clean_Internet_Setup_DBs" COMMAND "cmake" "-E" "remove_directory" "${RESULTS_NSSDB_INTERNET_OUTPUT_DIR}" ) jss_test_exec( NAME "Import_Internet_Certs" COMMAND "${CMAKE_SOURCE_DIR}/tools/common_roots.sh" "${RESULTS_NSSDB_INTERNET_OUTPUT_DIR}" DEPENDS "Clean_Internet_Setup_DBs" ) endif() jss_test_exec( NAME "TestBufferPRFD" COMMAND "${BIN_OUTPUT_DIR}/TestBufferPRFD" ) jss_test_java( NAME "Test_UTF-8_Converter" COMMAND "org.mozilla.jss.tests.UTF8ConverterTest" ) jss_test_java( NAME "Test_Base64_Parsing" COMMAND "org.mozilla.jss.tests.Base64Parsing" ) jss_test_java( NAME "JSS_DER_Encoding_of_Enumeration_regression_test" COMMAND "org.mozilla.jss.tests.EnumerationZeroTest" ) jss_test_java( NAME "JSS_Test_DER_Encoding_Functionality" COMMAND "org.mozilla.jss.tests.DEROutputStreamTests" ) jss_test_java( NAME "JSS_Test_Empty_DER_Value" COMMAND "org.mozilla.jss.tests.EmptyDerValue" ) jss_test_java( NAME "BigObjectIdentifier" COMMAND "org.mozilla.jss.tests.BigObjectIdentifier" ) jss_test_java( NAME "JSS_Test_PR_FileDesc" COMMAND "org.mozilla.jss.tests.TestPRFD" ) jss_test_java( NAME "JSS_Test_Raw_SSL" COMMAND "org.mozilla.jss.tests.TestRawSSL" "${RESULTS_NSSDB_OUTPUT_DIR}" DEPENDS "Setup_DBs" ) jss_test_java( NAME "JSS_Test_Buffer" COMMAND "org.mozilla.jss.tests.TestBuffer" ) jss_test_java( NAME "JSS_Test_GlobalRefProxy" COMMAND "org.mozilla.jss.tests.TestGlobalReference" MODE "NONE" ) if ((${Java_VERSION_MAJOR} EQUAL 1) AND (${Java_VERSION_MINOR} LESS 9) AND (${JSS_VERSION_BETA} EQUAL 1)) jss_test_java( NAME "Test_PKCS11Constants.java_for_Sun_compatibility" COMMAND "org.mozilla.jss.tests.TestPKCS11Constants" ) endif() jss_test_java( NAME "JUnit_BMPStringTest" COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.BMPStringTest" ) jss_test_java( NAME "JUnit_IA5StringTest" COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.IA5StringTest" ) jss_test_java( NAME "JUnit_PrintableStringTest" COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.PrintableStringTest" ) jss_test_java( NAME "JUnit_TeletexStringTest" COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.TeletexStringTest" ) jss_test_java( NAME "JUnit_UniversalStringTest" COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.UniversalStringTest" ) jss_test_java( NAME "JUnit_UTF8StringTest" COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.UTF8StringTest" ) jss_test_exec( NAME "buffer_size_1" COMMAND "${BIN_OUTPUT_DIR}/buffer_size_1" DEPENDS "generate_c_buffer_size_1" ) jss_test_exec( NAME "buffer_size_4" COMMAND "${BIN_OUTPUT_DIR}/buffer_size_4" DEPENDS "generate_c_buffer_size_4" ) jss_test_java( NAME "JUnit_CertificateChainTest" COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.CertificateChainTest" ) jss_test_java( NAME "JUnit_ChainSortingTest" COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.ChainSortingTest" ) jss_test_java( NAME "Generate_known_RSA_cert_pair" COMMAND "org.mozilla.jss.tests.GenerateTestCert" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" "20" "localhost" "SHA-256/RSA" "CA_RSA" "Server_RSA" "Client_RSA" DEPENDS "Setup_DBs" ) jss_test_java( NAME "Generate_known_ECDSA_cert_pair" COMMAND "org.mozilla.jss.tests.GenerateTestCert" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" "30" "localhost" "SHA-256/EC" "CA_ECDSA" "Server_ECDSA" "Client_ECDSA" DEPENDS "Generate_known_RSA_cert_pair" ) jss_test_exec( NAME "Create_PKCS11_cert_to_PKCS12_rsa.pfx" COMMAND "pk12util" "-o" "${RESULTS_NSSDB_OUTPUT_DIR}/rsa.pfx" "-n" "CA_RSA" "-d" "${RESULTS_NSSDB_OUTPUT_DIR}" "-K" "${DB_PWD}" "-W" "${DB_PWD}" DEPENDS "Generate_known_RSA_cert_pair" ) jss_test_exec( NAME "Create_PKCS11_cert_to_PKCS12_ecdsa.pfx" COMMAND "pk12util" "-o" "${RESULTS_NSSDB_OUTPUT_DIR}/ecdsa.pfx" "-n" "CA_ECDSA" "-d" "${RESULTS_NSSDB_OUTPUT_DIR}" "-K" "${DB_PWD}" "-W" "${DB_PWD}" DEPENDS "Generate_known_ECDSA_cert_pair" ) jss_test_java( NAME "List_CA_certs" COMMAND "org.mozilla.jss.tests.ListCACerts" "${RESULTS_NSSDB_OUTPUT_DIR}" "Verbose" DEPENDS "Generate_known_ECDSA_cert_pair" ) jss_test_java( NAME "SSLClientAuth" COMMAND "org.mozilla.jss.tests.SSLClientAuth" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" "${JSS_TEST_PORT_CLIENTAUTH}" "50" DEPENDS "List_CA_certs" ) jss_test_java( NAME "Key_Generation" COMMAND "org.mozilla.jss.tests.TestKeyGen" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "Setup_DBs" ) jss_test_java( NAME "Digest" COMMAND "org.mozilla.jss.tests.DigestTest" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "Setup_DBs" ) jss_test_java( NAME "HMAC" COMMAND "org.mozilla.jss.tests.CrossHMACTest" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "Setup_DBs" ) jss_test_java( NAME "KeyWrapping" COMMAND "org.mozilla.jss.tests.JCAKeyWrap" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "Setup_DBs" ) if(HAVE_NSS_OAEP) jss_test_java( NAME "JSS-KeyWrapping" COMMAND "org.mozilla.jss.tests.KeyWrapping" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "Setup_DBs" ) endif() jss_test_java( NAME "Mozilla_JSS_JCA_Signature" COMMAND "org.mozilla.jss.tests.JCASigTest" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "Setup_DBs" ) jss_test_java( NAME "Mozilla_JSS_NSS_Signature" COMMAND "org.mozilla.jss.tests.SigTest" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "Setup_DBs" ) jss_test_java( NAME "JSS_Signature_test" COMMAND "org.mozilla.jss.tests.SigTest" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "Setup_DBs" ) jss_test_java( NAME "Secret_Decoder_Ring" COMMAND "org.mozilla.jss.tests.TestSDR" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "Setup_DBs" ) jss_test_java( NAME "List_cert_by_certnick" COMMAND "org.mozilla.jss.tests.ListCerts" "${RESULTS_NSSDB_OUTPUT_DIR}" "Server_RSA" DEPENDS "Setup_DBs" ) jss_test_java( NAME "Verify_cert_by_certnick" COMMAND "org.mozilla.jss.tests.VerifyCert" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" "Server_RSA" DEPENDS "Setup_DBs" ) jss_test_java( NAME "Secret_Key_Generation" COMMAND "org.mozilla.jss.tests.SymKeyGen" "${RESULTS_NSSDB_OUTPUT_DIR}" DEPENDS "Setup_DBs" ) jss_test_java( NAME "Symmetric_Key_Deriving" COMMAND "org.mozilla.jss.tests.SymKeyDeriving" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "Setup_DBs" ) jss_test_java( NAME "X509CertTest" COMMAND "org.mozilla.jss.tests.X509CertTest" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "List_CA_certs" ) jss_test_java( NAME "KeyStoreTest" COMMAND "org.mozilla.jss.tests.KeyStoreTest" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" getAliases DEPENDS "List_CA_certs" "X509CertTest" "Secret_Key_Generation" "Symmetric_Key_Deriving" "SSLClientAuth" ) jss_test_java( NAME "JSSProvider" COMMAND "org.mozilla.jss.tests.JSSProvider" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "List_CA_certs" "X509CertTest" "Secret_Key_Generation" "Symmetric_Key_Deriving" "SSLClientAuth" ) jss_test_java( NAME "SSLEngine_RSA" COMMAND "org.mozilla.jss.tests.TestSSLEngine" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" "Client_RSA" "Server_RSA" DEPENDS "List_CA_certs" ) jss_test_java( NAME "SSLEngine_ECDSA" COMMAND "org.mozilla.jss.tests.TestSSLEngine" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" "Client_ECDSA" "Server_ECDSA" DEPENDS "SSLEngine_RSA" ) if(NOT FIPS_ENABLED) jss_test_java( NAME "Key_Factory" COMMAND "org.mozilla.jss.tests.KeyFactoryTest" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "Setup_DBs" ) jss_test_java( NAME "HMAC_Unwrap" COMMAND "org.mozilla.jss.tests.HmacTest" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "Setup_DBs" ) if(HAVE_NSS_CMAC) jss_test_java( NAME "CMAC_Test" COMMAND "org.mozilla.jss.tests.TestCmac" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "Setup_DBs" ) endif() if(HAVE_NSS_KBKDF) jss_test_java( NAME "KBKDF_Test" COMMAND "org.mozilla.jss.tests.TestKBKDF" "${RESULTS_NSSDB_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "Setup_DBs" ) endif() jss_test_java( NAME "Mozilla_JSS_Secret_Key_Generation" COMMAND "org.mozilla.jss.tests.JCASymKeyGen" "${RESULTS_NSSDB_OUTPUT_DIR}" DEPENDS "Setup_DBs" ) # SSL Engine related tests jss_test_exec( NAME "TestBufferPRFDSSL_RSA" COMMAND "${BIN_OUTPUT_DIR}/TestBufferPRFDSSL" "${RESULTS_NSSDB_OUTPUT_DIR}" "${DB_PWD}" "Server_RSA" DEPENDS "List_CA_certs" "generate_c_TestBufferPRFDSSL" ) jss_test_exec( NAME "TestBufferPRFDSSL_ECDSA" COMMAND "${BIN_OUTPUT_DIR}/TestBufferPRFDSSL" "${RESULTS_NSSDB_OUTPUT_DIR}" "${DB_PWD}" "Server_ECDSA" DEPENDS "List_CA_certs" "generate_c_TestBufferPRFDSSL" ) jss_test_java( NAME "JSS_Test_BufferPRFD" COMMAND "org.mozilla.jss.tests.TestBufferPRFD" "${RESULTS_NSSDB_OUTPUT_DIR}" "${DB_PWD}" DEPENDS "List_CA_certs" ) # FIPS-related tests jss_test_java( NAME "Generate_FIPS_known_RSA_cert_pair" COMMAND "org.mozilla.jss.tests.GenerateTestCert" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}" "70" "localhost" "SHA-256/RSA" "CA_RSA" "Server_RSA" "Client_RSA" DEPENDS "Setup_FIPS_DBs" MODE "FIPS" ) jss_test_java( NAME "Generate_FIPS_known_ECDSA_cert_pair" COMMAND "org.mozilla.jss.tests.GenerateTestCert" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}" "80" "localhost" "SHA-256/EC" "CA_ECDSA" "Server_ECDSA" "Client_ECDSA" DEPENDS "Generate_FIPS_known_RSA_cert_pair" MODE "FIPS" ) jss_test_java( NAME "Enable_FipsMODE" COMMAND "org.mozilla.jss.tests.FipsTest" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "enable" DEPENDS "Generate_FIPS_known_ECDSA_cert_pair" MODE "NONE" ) jss_test_java( NAME "check_FipsMODE" COMMAND "org.mozilla.jss.tests.FipsTest" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "chkfips" DEPENDS "Enable_FipsMODE" MODE "NONE" ) # The current version of NSS features partial support for TLS 1.3 in # FIPS mode. if (NOT SANDBOX) jss_test_java( NAME "SSLClientAuth_FIPSMODE" COMMAND "org.mozilla.jss.tests.SSLClientAuth" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}" "${JSS_TEST_PORT_CLIENTAUTH_FIPS}" "60" DEPENDS "Enable_FipsMODE" MODE "FIPS" ) else() jss_test_java( NAME "SSLClientAuth_FIPSMODE" COMMAND "org.mozilla.jss.tests.JSSProvider" DEPENDS "Enable_FipsMODE" MODE "FIPS" ) endif() jss_test_java( NAME "HMAC_FIPSMODE" COMMAND "org.mozilla.jss.tests.CrossHMACTest" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "Enable_FipsMODE" MODE "FIPS" ) jss_test_java( NAME "KeyWrapping_FIPSMODE" COMMAND "org.mozilla.jss.tests.JCAKeyWrap" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "Enable_FipsMODE" MODE "FIPS" ) jss_test_java( NAME "Mozilla_JSS_JCA_Signature_FIPSMODE" COMMAND "org.mozilla.jss.tests.JCASigTest" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "Enable_FipsMODE" MODE "FIPS" ) jss_test_java( NAME "JSS_Signature_test_FipsMODE" COMMAND "org.mozilla.jss.tests.SigTest" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}" DEPENDS "Enable_FipsMODE" MODE "FIPS" ) jss_test_java( NAME "SSLEngine_RSA_FIPSMODE" COMMAND "org.mozilla.jss.tests.TestSSLEngine" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}" "Client_RSA" "Server_RSA" DEPENDS "Enable_FipsMODE" "SSLEngine_ECDSA" MODE "FIPS" ) jss_test_java( NAME "SSLEngine_ECDSA_FIPSMODE" COMMAND "org.mozilla.jss.tests.TestSSLEngine" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "${PASSWORD_FILE}" "Client_ECDSA" "Server_ECDSA" DEPENDS "SSLEngine_RSA_FIPSMODE" "SSLEngine_ECDSA" MODE "FIPS" ) # Since we need to disable FIPS mode _after_ all FIPS-mode tests have # run, we have to add a strict dependency from Disable_FipsMODE onto all # FIPS-related checks. jss_test_java( NAME "Disable_FipsMODE" COMMAND "org.mozilla.jss.tests.FipsTest" "${RESULTS_NSSDB_FIPS_OUTPUT_DIR}" "disable" DEPENDS "check_FipsMODE" "SSLClientAuth_FIPSMODE" "HMAC_FIPSMODE" "KeyWrapping_FIPSMODE" "Mozilla_JSS_JCA_Signature_FIPSMODE" "JSS_Signature_test_FipsMODE" "SSLEngine_RSA_FIPSMODE" "SSLEngine_ECDSA_FIPSMODE" MODE "NONE" ) endif() jss_test_java( NAME "JUnit_GenericValueConverterTest" COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.GenericValueConverterTest" ) jss_test_java( NAME "JUnit_IA5StringConverterTest" COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.IA5StringConverterTest" ) jss_test_java( NAME "JUnit_PrintableConverterTest" COMMAND "org.junit.runner.JUnitCore" "org.mozilla.jss.tests.PrintableConverterTest" ) if(TEST_WITH_INTERNET) jss_test_java( NAME "BadSSL" COMMAND "org.mozilla.jss.tests.BadSSL" "${RESULTS_NSSDB_INTERNET_OUTPUT_DIR}" DEPENDS "Import_Internet_Certs" MODE "INTERNET" ) jss_test_java( NAME "BadSSL_Leaf_And_Chain" COMMAND "org.mozilla.jss.tests.BadSSL" "${RESULTS_NSSDB_INTERNET_OUTPUT_DIR}" "LEAF_AND_CHAIN" DEPENDS "Import_Internet_Certs" MODE "INTERNET" ) endif() # For compliance with several existing clients add_custom_target( check DEPENDS test ) endmacro() macro(jss_tests_compile) jss_tests_compile_c("${PROJECT_SOURCE_DIR}/src/test/java/org/mozilla/jss/tests/buffer_size_1.c" "${BIN_OUTPUT_DIR}/buffer_size_1" "buffer_size_1") jss_tests_compile_c("${PROJECT_SOURCE_DIR}/src/test/java/org/mozilla/jss/tests/buffer_size_4.c" "${BIN_OUTPUT_DIR}/buffer_size_4" "buffer_size_4") jss_tests_compile_c("${PROJECT_SOURCE_DIR}/src/test/java/org/mozilla/jss/tests/TestBufferPRFD.c" "${BIN_OUTPUT_DIR}/TestBufferPRFD" "TestBufferPRFD") jss_tests_compile_c("${PROJECT_SOURCE_DIR}/src/test/java/org/mozilla/jss/tests/TestBufferPRFDSSL.c" "${BIN_OUTPUT_DIR}/TestBufferPRFDSSL" "TestBufferPRFDSSL") endmacro() macro(jss_tests_compile_c C_FILE C_OUTPUT C_TARGET) # Generate the target executable from C_FILE add_custom_command( OUTPUT "${C_OUTPUT}" COMMAND ${CMAKE_C_COMPILER} ${JSS_C_FLAGS} -o ${C_OUTPUT} ${C_FILE} -L${LIB_OUTPUT_DIR} -ljss ${JSS_LD_FLAGS} WORKING_DIRECTORY ${C_DIR} DEPENDS "${C_FILE}" DEPENDS "${JSS_TESTS_SO_PATH}" DEPENDS generate_java DEPENDS generate_includes ) add_custom_target( "generate_c_${C_TARGET}" DEPENDS "${C_OUTPUT}" ) add_dependencies("generate_so" "generate_c_${C_TARGET}") endmacro() function(jss_test_java) set(TEST_FLAGS "NAME") set(TEST_ARGS "COMMAND" "DEPENDS" "MODE") cmake_parse_arguments(TEST_JAVA "" "${TEST_FLAGS}" "${TEST_ARGS}" ${ARGN}) list(APPEND EXEC_COMMAND "${Java_JAVA_EXECUTABLE}") list(APPEND EXEC_COMMAND "-classpath") list(APPEND EXEC_COMMAND "${TEST_CLASSPATH}") list(APPEND EXEC_COMMAND "-ea") list(APPEND EXEC_COMMAND "-Djava.library.path=${CMAKE_BINARY_DIR}") if(TEST_JAVA_MODE STREQUAL "FIPS") list(APPEND EXEC_COMMAND "-Djava.security.properties=${CONFIG_OUTPUT_DIR}/fips.security") elseif(TEST_JAVA_MODE STREQUAL "INTERNET") list(APPEND EXEC_COMMAND "-Djava.security.properties=${CONFIG_OUTPUT_DIR}/internet.security") elseif(NOT TEST_JAVA_MODE STREQUAL "NONE") list(APPEND EXEC_COMMAND "-Djava.security.properties=${CONFIG_OUTPUT_DIR}/java.security") endif() if(CMAKE_BUILD_TYPE STREQUAL "Debug") list(APPEND EXEC_COMMAND "-Djava.util.logging.config.file=${PROJECT_SOURCE_DIR}/tools/logging.properties") endif() set(EXEC_COMMAND "${EXEC_COMMAND};${TEST_JAVA_COMMAND}") if(TEST_JAVA_DEPENDS) jss_test_exec( NAME "${TEST_JAVA_NAME}" COMMAND "${EXEC_COMMAND}" DEPENDS ${TEST_JAVA_DEPENDS} LIBRARY "java" ) else() jss_test_exec( NAME "${TEST_JAVA_NAME}" COMMAND "${EXEC_COMMAND}" LIBRARY "java" ) endif() endfunction() macro(jss_test_exec) # Usage: # # jss_test_exec( # NAME TEST_NAME # COMMAND TEST_COMMAND # [DEPENDS [TEST_DEPENDS TEST_DEPENDS...]] # # Note that TEST_COMMAND can be a list by quoting the list: # # jss_test_exec("NAME" "ARG1" "ARG2" "...") set(TEST_FLAGS "NAME" "LIBRARY") set(TEST_ARGS "COMMAND" "DEPENDS") cmake_parse_arguments(TEST_EXEC "" "${TEST_FLAGS}" "${TEST_ARGS}" ${ARGN}) if(TEST_VALGRIND) list(INSERT TEST_EXEC_COMMAND 0 "valgrind" "--track-origins=yes" "--leak-check=full") endif() add_test( NAME "${TEST_EXEC_NAME}" COMMAND ${TEST_EXEC_COMMAND} ) list(APPEND LD_LIBRARY ${NSS_LIBRARIES}) list(APPEND LD_LIBRARY ${NSPR_LIBRARIES}) # If we are calling a java program, use the versioned library to ensure # that any new JNI calls are made visible. if(TEST_EXEC_LIBRARY AND (TEST_EXEC_LIBRARY STREQUAL "java")) list(APPEND LD_LIBRARY "${CMAKE_BINARY_DIR}") list(REMOVE_DUPLICATES LD_LIBRARY) jss_list_join(LD_LIBRARY ":" LD_LIBRARY_PATH) set_tests_properties( "${TEST_EXEC_NAME}" PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" ) else() list(APPEND LD_LIBRARY "${LIB_OUTPUT_DIR}") list(REMOVE_DUPLICATES LD_LIBRARY) jss_list_join(LD_LIBRARY ":" LD_LIBRARY_PATH) set_tests_properties( "${TEST_EXEC_NAME}" PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${LD_LIBRARY_PATH}" ) endif() if(TEST_EXEC_DEPENDS) set_tests_properties( "${TEST_EXEC_NAME}" PROPERTIES DEPENDS "${TEST_EXEC_DEPENDS}" ) endif() endmacro() jss-5.0.0/cmake/Shims.cmake000066400000000000000000000010241412550063600154570ustar00rootroot00000000000000# LIST(JOIN ...) was introduced in CMake verison 3.12 macro(jss_list_join LIST_ SEPARATOR_ VAR_) if(${CMAKE_VERSION} VERSION_LESS "3.12.0") set("${VAR_}" "") foreach(ELEMENT ${${LIST_}}) set("${VAR_}" "${${VAR_}}${SEPARATOR_}${ELEMENT}") endforeach() string(LENGTH "${SEPARATOR_}" JSS_LIST_JOIN_SEPARATOR_LENGTH) string(SUBSTRING "${${VAR_}}" ${JSS_LIST_JOIN_SEPARATOR_LENGTH} -1 "${VAR_}") else() list(JOIN ${LIST_} ${SEPARATOR_} ${VAR_}) endif() endmacro() jss-5.0.0/docs/000077500000000000000000000000001412550063600132455ustar00rootroot00000000000000jss-5.0.0/docs/build_system.md000066400000000000000000000130721412550063600162750ustar00rootroot00000000000000# Build System This document describes the CMake build system and various locations used by CMake. ## Overview The new build system relies on CMake to build JSS. Most of the functionality is located under the `cmake/` directory in the root of the project. JSS is built in five stages: 1. Classes are built from Java source and JNI headers are generated. This is done in a single pass of the `javac` compiler. All Java source files under `src/main/java/` are currently compiled to the `build/classes/` folder. 2. Any C header files are moved to the `build/includes/` folder. 3. C source files are compiled to objects and linked to form `libjss.so`, excluding any C source files in `src/test/java/`. If any exist, they'll be compiled at a later stage for `ctest`. This step is dependent on steps 1 and 2. 4. Build the JAR archive from compiled Java classes. Note that at this time, all classes in `build/classes/` are compiled into one JAR; in the future, a white list might be applied and testing classes separated out into a different JAR. This is dependent on step 1. 5. (Optionally) build Javadocs. This requires the user to build the `javadoc` target. The test suite is also generated using CMake in `cmake/JSSTests.cmake`. This allows JSS to run its test in parallel. ## `CMakeLists.txt` This is a file required by CMake for all CMake projects; it defines how the project is built. We use it as a high-level overview of CMake: options are defined, environment variables are read, modules are imported, and JSS is built and tested through here. JSS uses a direct approach to building: as a single call to `javac` suffices to build all of our classes and JNI headers, we don't need a recursive structure to build. This lets us have only one `CMakeLists.txt` in the root of our project. ## `cmake/` This directory contains two sets of files: dependencies and core modules. The non-standard CMake dependencies currently include the `FindNSPR` and `FindNSS` modules: these allow CMake to find NSPR and NSS system libraries and were imported from PKI. The core modules include `JSSConfig`, which sets useful variables for use within CMake, `JSSCommon`, which controls building JSS, and `JSSTests`, which sets up the JSS test suite within CTest. ### Available CMake Options Our CMake generator currently understands the following options when configuring the build system. Each option can either be specified on the CMake command line with `-D=` syntax, or in the environment. - `CHECK_DEPRECATION` -- enable `-Xlint:deprecation` when compiling JSS to check for use of deprecated APIs. - `FIPS_ENABLED` -- disable certain test cases which are known to fail in FIPS mode for various reasons. These usually include tests which try to disable FIPS mode, use unsupported ciphers, or too small of key sizes. Note that NSS must still be built with FIPS mode support enabled. - `SANDBOX` -- support building sandboxed builds to test changes to NSPR or NSS alongside changes to JSS. This assumes you have the following directory structure: ``` sandbox/ sandbox/nspr sandbox/nss sandbox/dist sandbox/jss ``` Note that `sandbox` can be replaced by any directory name. The `sandbox/dist` folder is automatically created by NSS upon build. Please first build NSS (according to current instructions) and then build JSS. - `TEST_VALGRIND` -- run the entire test suite under Valgrind. This option is quite slow. By default it passes two arguments: `--track-origins=yes` and `--leak-check=full`. Modify `cmake/JSSTests.cmake` (macro: `jss_test_exec`) to change these options. - `WITH_INTERNET` -- run tests which require an internet connection. This exposes your system to other hosts on the internet, including badssl.com and www.mozilla.org. Correct execution requires a working `common_roots.sh` script under `tools/`; update for your system as necessary. ### Adding a Test Case To add a new test case, add an entry to `cmake/JSSTests.cmake`. There's two useful helpers macros `jss_test_exec` and `jss_test_java`. `jss_test_exec` takes a `NAME` parameter (to use to identify the test case in output and when running particular tests), a `COMMAND` to execute, and an optional set of dependencies (`DEPENDS ...`) on other tests. We use this because `add_test` doesn't itself handle dependencies or set environment variables (we need to inject `LD_LIBRARY_PATH` to handle testing our built `libjss.so`). `jss_test_java` is a wrapper over `jss_test_exec` which handles setting up the JVM and passing required arguments to it (`-classpath`, `-enableasserts`, etc.). Pass only the class you wish to execute and any arguments to it as the COMMAND field. (e.g., `COMMAND "org.mozilla.jss.tests.TestBuffer"`). There are a few useful variables defined: - `JSS_TEST_DIR` -- directory to the souce code where the tests are contained. - `PASSWORD_FILE` -- password for the NSS DB tokens. - `DB_PWD` -- password for the NSS DB internal (default) token. - `RESULTS_DATA_OUTPUT_DIR` -- directory to write test results to. - `RESULTS_NSSDB_OUTPUT_DIR` -- path of the non-FIPS NSS DB. - `RESULTS_NSSDB_FIPS_OUTPUT_DIR` -- path of the FIPS NSS DB. Note that, on a FIPS-enabled machine, `RESULTS_NSSDB_FIPS_OUTPUT_DIR` is unused and `RESULTS_NSSDB_OUTPUT_DIR` is actually placed in FIPS mode. For tests which would fail in FIPS mode, place them in the `if(NOT FIPS_ENABLED)` block. ## `lib/` This includes a few templated files including `jss.map`, the linker script which contains a versioned API of JSS, and `MANIFEST.MF.in`, JSS's Jar manifest file. jss-5.0.0/docs/building.md000066400000000000000000000047511412550063600153730ustar00rootroot00000000000000# Building JSS As of version 4.5.1, JSS has moved to a CMake build system. This is a modern alternative to our legacy build system and gives us a standard framework for building and testing JSS. This also allows us to support parallel builds and tests; to take advantage of this, specify the `-j` flag when using `make` or `ctest`. Please make sure the required dependencies are installed prior to building (see: [`docs/dependencies`](dependencies.md)). ## In-Source Build To build JSS from the source release, use `cmake`; JSS behaves much like a regular CMake project. ### Building JSS To build JSS using CMake: cd jss/build cmake .. make all To later rebuild from scratch, remove the build directory and recreate it. This ensures that any new dependencies are reflected in the build system. cd jss rm -rf build && mkdir build && cd build cmake .. make all ### Building Documentation Optionally, build the javadocs: cd jss/build make javadoc ### Testing To run the test suite: cd jss/build make test Note that the test suite currently doesn't handling re-running without clearing the results directory. To re-run the test suite: cd jss/build rm -rf results mkdir -p results/tests results/fips make test Alternatively, use CTest to run the test suite: ctest --output-on-failure Helpful flags for ctest are `--verbose` and `--output-log`; for more information, read `man ctest`. ### Installation To install JSS, place `jss.jar` and `libjss.so` in places where the system can find them. We recommend the following locations on a 64-bit system: cd jss/build sudo cp jss.jar /usr/lib/java/jss.jar sudo chown root:root /usr/lib/java/jss.jar sudo chmod 644 /usr/lib/java/jss.jar sudo cp libjss.so /usr/lib64/jss/libjss.so sudo chown root:root /usr/lib64/jss/libjss.so sudo chmod 755 /usr/lib64/jss/libjss.so To uninstall, simply remove the created files (`/usr/lib/java/jss.jar` and `/usr/lib64/jss/libjss.so`). Note that the preferred way to install JSS is from your distribution or via an RPM built with `build.sh`. ## RPM Builds To build a RPM release, please ensure all dependencies are installed: sudo dnf install rpm-build cd jss && sudo dnf builddep --spec jss.spec Then, issue a build using the `build.sh` interface: ./build.sh rpm This will build RPMS and place them in `$HOME/build/jss` by default. For more information about this build script, refer to its help text: ./build.sh --help jss-5.0.0/docs/changes/000077500000000000000000000000001412550063600146555ustar00rootroot00000000000000jss-5.0.0/docs/changes/v5.0.0/000077500000000000000000000000001412550063600155035ustar00rootroot00000000000000jss-5.0.0/docs/changes/v5.0.0/API-Changes.adoc000066400000000000000000000012201412550063600203050ustar00rootroot00000000000000= API Changes = == Changes in org.mozilla.jss.netscape.security.x509.CertAndKeyGen == * The `getSelfCert()` has been deprecated in JSS 4 and dropped in JSS 5. Use `getSelfCertificate()` instead. * The `setRandom()` has been deprecated in JSS 4 and dropped in JSS 5. It is no longer used. == Changes in org.mozilla.jss.netscape.security.x509.X509Cert == The class has been deprecated in JSS 4 and dropped in JSS 5. Use `java.security.cert.Certificate` instead. == Changes in org.mozilla.jss.netscape.security.x509.RevocationReasonAdapter == The class has been deprecated in JSS 4 and dropped in JSS 5. Use the revocation reason code or label instead. jss-5.0.0/docs/ci.md000066400000000000000000000022201412550063600141560ustar00rootroot00000000000000# Containers and Continuous Integration JSS uses [Travis CI](https://travis-ci.org/dogtagpki/jss) for PR gating. We use Linux containers to ensure a consistent build environment and to allow us to test locally and in Travis on various platforms. ## Running CI Locally The Docker images are built in Travis using the Dockerfiles in `tools/Dockerfiles`; they are not pushed to DockerHub or similar platforms at this time. To test locally, we recommend using the provided container tool, `tools/run_container.sh`. For a brief example: ```bash cd /path/to/sandbox/jss ./tools/run_container.sh fedora_28 ``` Note that this requires either Buildah and Podman or Docker to be installed. For more extensive documentation, please refer to the [Buildah](https://github.com/containers/buildah/blob/master/docs/) and [Podman docs](https://github.com/containers/libpod/tree/master/docs) and the code in the `tools/run_container.sh` script. ## Skipping CI To skip running CI for a given commit (e.g., for updating documentation), append `[skip ci]` to the commit summary. Note that the `ubuntu_jdk8` image does not affect build status; it is included for reference only. jss-5.0.0/docs/contributing.md000066400000000000000000000051231412550063600162770ustar00rootroot00000000000000# Contributing to JSS We welcome all contributions to JSS and thank you in advance for them! Below are a few ways of contributing to JSS. ## Filing a Downstream Issue If you're using JSS as shipped by a distribution, we recommend filing an issue downstream first. In the case of a [RHCS](https://www.redhat.com/en/technologies/cloud-computing/certificate-system), [RHEL](https://www.redhat.com/en/technologies/cloud-computing/certificate-system), or [Fedora](https://getfedora.org/) release, the correct bugtracker is the [Red Hat Bugzilla](https://bugzilla.redhat.com/) instance. If you don't hear a response at the appropriate downstream tracker or if you think the issue exists upstream as well, feel free to file an upstream issue. ## Filing an Upstream Issue JSS's issue tracker can be found on [GitHub](https://github.com/dogtagpki/jss/issues) under the [Dogtag PKI organization](https://github.com/dogtagpki). Note that this requires a GitHub account to create bugs. ### Legacy Issue Trackers In the past, JSS has used the following issue trackers. Unfortunately, we cannot monitor them and we were not able to migrate all issues to the new sites. - [Pagure](https://pagure.io/jss/issues) - [Mozilla's Bugzilla instance](https://bugzilla.mozilla.org/buglist.cgi?classification=Components&list_id=15438920&query_format=advanced&product=JSS&component=Documentation&component=Library&component=Sample%20Code&component=Tests&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED&bug_status=RESOLVED&bug_status=VERIFIED&bug_status=CLOSED&resolution=---) ## Opening a Pull Request If you'd like to contribute code to JSS, feel free to open a pull request against JSS. We'd recommend filing an issue (see above) if you'd like to introduce major change to JSS. This gives us a place to discuss the changes before they are proposed. Please fork the repository and make your changes in a new branch; before proposing the pull request, rebase your branch against upstream master. To test JSS locally, follow the [build instructions](building.md). Additionally, it is possible to run the CI container instances locally; follow directions in the [CI Overview](ci.md). We'd suggest making sure a Fedora build passes (e.g., `fedora_28`) and the `stylecheck` image passes as well. Then, feel free to open a PR. If you're looking for more information, we suggest reading about the [GitHub Flow](https://guides.github.com/introduction/flow/index.html) and reaching out to the developers if you need any assistance. ## Contacting Us See [Contact Us](https://github.com/dogtagpki/pki/wiki/Contact-Us). Thanks! jss-5.0.0/docs/dependencies.md000066400000000000000000000043441412550063600162220ustar00rootroot00000000000000# Dependencies ## Build-time Dependencies This project has the following dependencies: - [NSPR](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSPR) - [NSS](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS) - A c and c++ compiler such as [gcc](ttps://gcc.gnu.org/) - [zlib](https://zlib.net/) - [OpenJDK 1.8.0 or newer](http://openjdk.java.net/) - [CMake](https://cmake.org/) - [Apache Commons Lang](https://commons.apache.org/proper/commons-lang/) - [SLF4J](https://www.slf4j.org/) Additionally, a zipping and unzipping program is required to create reproducible builds. To install these dependencies on Fedora, execute the following: sudo dnf install apache-commons-lang gcc-c++ java-devel jpackage-utils \ slf4j zlib-devel nss-tools nss-devel \ cmake junit To install these dependencies on Debian, execute the following: sudo apt-get install build-essential libcommons-lang-java libnss3-dev \ libslf4j-java default-jdk pkg-config zlib1g-dev \ libnss3-tools cmake zip unzip \ junit4 ## Test Suite Dependencies: In addition to the dependencies above, the test suite requires the following additional packages: - [SLF4J's JDK14 package](https://www.slf4j.org/api/org/slf4j/impl/JDK14LoggerAdapter.html) - [NSS's pk12util](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Reference/NSS_tools_:_pk12util) - [JUnit 4](https://junit.org/junit4/) To install these dependencies on Fedora, execute the following: sudo dnf install nss nss-tools slf4j-jdk14 junit To install these dependencies on Debian, execute the following: sudo apt-get install libnss3 libnss3-tools libslf4j-java \ junit4 ## Run-time Dependencies At run time, the following JARs are required to be specified on the `CLASSPATH` of anyone wishing to use JSS: - `jss.jar` - `slf4j-api.jar` - `apache-commons-lang.jar` Note that these should already be installed when building JSS. For more information, please refer to our documentation on using JSS: [`docs/using_jss.md`](using_jss.md). ## Incompatibilities Known NSS incompatibilities are documented in [`docs/nss.md`](nss.md). jss-5.0.0/docs/development/000077500000000000000000000000001412550063600155675ustar00rootroot00000000000000jss-5.0.0/docs/development/Synchronizing-GitLab-Branch.adoc000066400000000000000000000033661412550063600236260ustar00rootroot00000000000000= Synchronizing GitLab Branch = == Overview == This page describes the procedure to synchronize a branch from an upstream repository to a GitLab repository. == Creating Access Token == In the GitLab repository create a project access token with a **write_repository** permission. See link:https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html#creating-a-project-access-token[Creating a project access token]. == Configuring Synchronization == In the GitLab repository create the following variables: * `UPSTREAM_URL`: The URL of the upstream repository. ** Unselect **Protect variable** to synchronize unprotected branches. * `ACCESS_TOKEN`: The value of the access token. ** Unselect **Protect variable** to synchronize unprotected branches. ** Select **Mask variable** to keep the access token hidden. See link:https://docs.gitlab.com/ee/ci/variables/#add-a-cicd-variable-to-a-project[Add a CI/CD variable to a project]. == Running Synchronization Manually == In the GitLab repository run a pipeline with the following parameters: * **Run for branch name or tag**: The branch to be synchronized. * **Variables**: ** `SYNC`: `true` See link:https://docs.gitlab.com/ee/ci/pipelines/#run-a-pipeline-manually[Run a pipeline manually]. == Scheduling Automatic Synchronization == In the GitLab repository create a schedule with the following parameters: * **Interval Pattern**: The frequency of synchronization. ** To synchronize every hour, enter: `0 * * * *` * **Target Branch**: The branch to be synchronized. * **Variables**: ** `SYNC`: `true` Additional schedules can be created for synchronizing other branches. See link:https://docs.gitlab.com/ee/ci/pipelines/schedules.html#configuring-pipeline-schedules[Configuring pipeline schedules]. jss-5.0.0/docs/gh_pages.md000066400000000000000000000021751412550063600153510ustar00rootroot00000000000000# GitHub Pages JSS uses the GitHub pages functionality to host our generated javadocs. This allows developers to browse our documentation online without pulling down the JSS sources. Periodically, this documentation will need to be updated and will mirror the latest contents of master. To do so: 1. Checkout the master branch and make sure it is up to date with `upstream`: ``` cd sandbox/jss git remote add upstream https://github.com/dogtagpki/jss git fetch --all git checkout upstream/master ``` 2. Build the javadocs; note that they are placed in `../dist/jssdocs`: ``` export JAVA_HOME=/etc/alternatives/java_sdk_1.8.0_openjdk export USE_64=1 make javadoc ``` 3. Copy the new-docs into the gh-pages branch: ``` git clean -xdf && git checkout gh-pages rm -rf javadoc && cp ../dist/jssdoc javadoc -rv git add javadoc && git commit -m "Update javadocs from master at $(date '+%Y-%m-%d %H:%M')" && git push origin gh-pages ``` 4. Open a PR against `dogtagpki/jss` with the updates. This will get reviewed, merged, and then automatically propagated to GitHub Pages. jss-5.0.0/docs/legacy_building.md000066400000000000000000000150761412550063600167210ustar00rootroot00000000000000# Legacy Build Instructions These instructions have been preserved from the README; if you are referring to specific parts of the build instructions, they have been moved here. Build/Test Instructions ----------------------- ### 1. Prepare a work area (a) For upstream builds which checkout and utilize the current NSPR and NSS source repositories: ``` # mkdir sandbox # cd sandbox # hg clone https://hg.mozilla.org/projects/nspr # hg clone https://hg.mozilla.org/projects/nss # git clone git@github.com:dogtagpki/jss.git # cd .. ``` There is no need to clone every time. For additional builds, simply use: ``` # cd nspr # hg pull -u -v # cd .. # cd nss # hg pull -u -v # cd .. # cd jss # git pull -v # cd .. ```` (b) Alternatively, for upstream builds which use the NSPR and NSS installed on the system: ``` # mkdir sandbox # cd sandbox # export USE_INSTALLED_NSPR=1 # export USE_INSTALLED_NSS=1 # export PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 # export PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1 # export NSPR_INCLUDE_DIR=`/usr/bin/pkg-config --cflags-only-I nspr | sed 's/-I//'` # export NSPR_LIB_DIR=`/usr/bin/pkg-config --libs-only-L nspr | sed 's/-L//'` # export NSS_INCLUDE_DIR=`/usr/bin/pkg-config --cflags-only-I nss | sed 's/-I//'` # export NSS_LIB_DIR=`/usr/bin/pkg-config --libs-only-L nss | sed 's/-L//'` # export XCFLAGS="-g" # git clone https://hg.mozilla.org/projects/jss # cd .. ``` There is no need to clone every time. For additional builds, simply use: ``` # cd jss # git pull -v # cd .. ``` ### 2. Prepare an interactive shell for building ``` # export JAVA_HOME=/etc/alternatives/java_sdk_1.8.0_openjdk # export USE_64=1 ``` NOTE: JSS will now attempt to verify whether or not these two environment variables have been set (JAVA_HOME is mandatory; USE_64 is mandatory on 64-bit platforms when building 64-bit). The following steps are optional, and left to the discretion of the user: #### Normal vs. Optimized builds By default, JSS will be built as a normal binaries. To create an optimized build, set the following environment variable: ``` # export BUILD_OPT=1 ``` #### Beta vs. Non-Beta builds Finally, by default, JSS is not built as a "beta" release (as specified in 'org/mozilla/jss/util/jssver.h'): ``` #define JSS_BETA PR_FALSE ``` If a "beta" version of JSS is desired, reset this #define (as specified in 'org/mozilla/jss/util/jssver.h') to: ``` #define JSS_BETA PR_TRUE ``` ### 3. Build JSS To build JSS, execute the following commands: ``` # cd sandbox/jss # make clean all # cd ../.. ``` or you can run: ``` # script -c 'make clean all' typescript.build ``` NOTE: When build method (1)(a) is being utilized, if nss has not been built, it will now automatically be built before jss; if nss has already been built, only jss will be built/re-built. ### 4. Install JSS on the System (Optional) If JSS already exists on the system, run something similar to the following command(s): ``` # sudo mv /usr/lib/java/jss.jar /usr/lib/java/jss.jar.orig ``` If the platform is 32-bit Linux: ``` # sudo mv /usr/lib/jss/libjss.so /usr/lib/jss/libjss.so.orig ``` else if the platform is 64-bit Linux: ``` # sudo mv /usr/lib64/jss/libjss.so /usr/lib64/jss/libjss.so.orig ``` Then install the new JSS binaries: ``` # sudo cp sandbox/dist/xpclass.jar /usr/lib/java/jss.jar # sudo chown root:root /usr/lib/java/jss.jar # sudo chmod 644 /usr/lib/java/jss.jar # sudo cp sandbox/jss/lib/Linux*.OBJ/libjss.so /usr/lib64/jss/libjss.so # sudo chown root:root /usr/lib64/jss/libjss.so # sudo chmod 755 /usr/lib64/jss/libjss.so ``` ### 5. Run JSS Tests (Optional, but only if build method (1)(a) was utilized) If build method (1)(a) is being utilized, it is possible to run the built-in JSS tests: ``` # cd sandbox/jss # make test_jss # cd ../.. ``` or you can run: ``` # script -c 'make test_jss' typescript.tests ``` NOTE: This command is currently only available on Linux and Macintosh platforms when method (1)(a) has been utilized to build JSS since the tests are dependent upon the work area as setup in this method; currently JSS must be built via 'make clean all' before execution of this command (e.g. - build is separate from test). ### 6. Restoration of non-Test-Only Systems (Optional) If step (4) above was run, and the system is being used for purposes other than test, the user may wish to restore the original system JSS by running the following commands: ``` # sudo mv /usr/lib/java/jss.jar.orig /usr/lib/java/jss.jar ``` If the platform is 32-bit Linux: ``` # sudo mv /usr/lib/jss/libjss.so.orig /usr/lib/jss/libjss.so ``` else if the platform is 64-bit Linux: ``` # sudo mv /usr/lib64/jss/libjss.so.orig /usr/lib64/jss/libjss.so ``` NOTE: For this procedure, no ownership or permission changes should be necessary. ### 7. Tagging the Source Code for a Release During development, several releases may be made. Consequently, it is good practice to create a "regular tag" to the source code at these various points in time using the following format: ``` # git tag -m "message" JSS___ ``` where: * major = JSS Major Version Number * minor = JSS Minor Version Number * YYYY = 4-digit year (e. g. - 2017) * MM = 2-digit month (e. g. - 01, ..., 12) * DD = 2-digit day of the month (e. g. - 01, ..., 31) For example: ``` # git rev-parse HEAD b3e864205ff0... # git tag -m "Added tag JSS_4_4_20170328 for changeset b3e864205ff0" JSS_4_4_20170328 ``` At the appropriate time, a new major.minor version may be created. At this time, it is important to create a maintenance branch for any future changes to the previous major.minor version: For example: ``` # git rev-parse HEAD f00f00f00f00... # git checkout -b JSS_4_4_BRANCH ``` ### 8. Known Issues Some of the known issues are: * Mozilla Bug #1346410 - Load JSS libraries appropriately NOTE: This issue should not occur unless step (4) above was skipped. Testing failures were found while working on Bug 1346410 when loading the JSS libraries to meet requirements of certain operating systems. Our investigation revealed that due to the nature of the changes made via this patch and its interaction with the HMAC Tests (both non-FIPS and FIPS), that a failure may be encountered on one or more of the HMAC algorithms causing these two tests to fail. On 64-bit Linux, for example, the workaround for this issue is to perform the following steps before re-running the tests: * Install the new JSS builds by executing step (4) above * Execute the following commands: ``` # cd sandbox/jss # make test_jss ``` NOTE: If the system is being used for purposes other than test, the user may wish to restore the original JSS by executing step (6) above. jss-5.0.0/docs/nss.md000066400000000000000000000020411412550063600143670ustar00rootroot00000000000000# NSS ## Incompatible NSS/JSS Pairings The minimum NSS version required by JSS is v3.44. Up to v3.44, NSS didn't correctly support SECKEY_ConvertToPublicKey, returning NULL in some cases with an EC private key. This was fixed in v3.44. ### JSS v4.6.3 JSS v4.6.3 doesn't support NSS versions between v3.47 and v3.50, inclusive. This is because [moz-bz#1570501][moz-bz-1570501] introduced a bug that wasn't caught and fixed until [moz-bz#1611209][moz-bz-1611209]. NSS versions v3.46 and earlier will work but lack CMAC and KBKDF support, and NSS versions v3.51 and later will work and have CMAC and KBKDF support. JSS v4.6.4 introduces a check for working CMAC support (see the [pull request][pr-425] or commit 16c8de46bb8f03a9e6e3489e751114655a31f9bf). [moz-bz-1570501]: https://bugzilla.mozilla.org/show_bug.cgi?id=1570501 "Add CMAC to FreeBL and PKCS #11 libraries" [moz-bz-1611209]: https://bugzilla.mozilla.org/show_bug.cgi?id=1611209 "Value of CKM_AES_CMAC and CKM_AES_CMAC_GENERAL are swapped" [pr-425]: https://github.com/dogtagpki/jss/pull/425 jss-5.0.0/docs/pkcs11_constants.md000066400000000000000000000124041412550063600167660ustar00rootroot00000000000000# PKCS11Constants As of release 4.5.1, JSS now ships with a set of constants that enable JSS to work on JDK versions greater than 8. In particular, JDK 9+ introduced the concepts of Modules to Java, allowing previously exported classes to be restricted. This resulted in the complete removal of all `sun.*` classes; previously, these internal implementation details were exposed by the JDK. These changes are documented more at the following locations: - https://www.oracle.com/technetwork/java/faq-sun-packages-142232.html - https://www.oracle.com/corporate/features/understanding-java-9-modules.html - https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=875589 - https://wiki.debian.org/Java/Java9Pitfalls As a replacement, we built a utility to convert NSS's header files (`pkcs11t.h` and `pkcs11n.h`) to Java. The following sections describe this system. ## Regenerating PKCS11Constants.java There are a few cases where updating PKCS11Constants.java is necessary: - If NSS updates either of the two header files. - If certain constants need to be excluded. - If new constants need to be included. In the former case, the CI job or container build of `pkcs11checks` will fail, notifying us that this will need to be updated. To do so, first make sure the system's NSS is up to date: dnf update --refresh dnf install nss-dev Then, validate the location of the NSS header files; on Fedora, this location is `/usr/include/nss3`: ls /usr/include/nss3/pkcs11{t,n}.h Lastly, run the utility: python3 ./tools/build_pkcs11_constants.py --system \ --pkcs11t /usr/include/nss3/pkcs11t.h \ --pkcs11n /usr/include/nss3/pkcs11n.h \ --output src/main/java/org/mozilla/jss/pkcs11/PKCS11Constants.java While not required, it is suggested to use the `--system` flag to ensure the values of `PKCS11Constants.java` are the same as the installed NSS values. After this, rebuild JSS and run the test suite on a JDK8 machine: source ./tools/autoenv.sh cd build && cmake .. && make clean all check This will trigger the interoperability tests against the Sun values. ## `tools/build_pkcs11_constants.py` This utility generates the `PKCS11Constants.java` from the contents of the NSS header files. It has the following flags: -h / --help :: display the help text associated with the script --pkcs11t :: path to the pkcs11t.h header file from a NSS distribution; this header file contains the general PKCS11 constants --pkcs11n :: path to the pkcs11n.h header file from a NSS distribution; this header file contains NSS and Netscape-specific PKCS11 Constants -o / --output :: path to output the generated Java file to -s / --system :: assume the provided headers are from the system-installed NSS; perform extended sanity checks by compiling the parsed values and checking them against the NSS values -v / --verbose :: generate extended debug information in the form of comments in the generated file; this includes information about parsing, resolution, and if applicable, the output of the system checks The code of this program is heavily documented and is roughly organized from more specific methods to more general methods (e.g., `main`). A few things are of particular note: - This program attempts to verify correctness by ensuring that the internal representation of a constant is as a Python `int`; this ensures that we correctly parsed the value token and that, when we write the output, the value doesn't depend on any other constants. - This program treats all `#define`-d constants as if they were of a numeric type, with all values being written as hex encoded longs. - This program preserves the original ordering of constants, with constants in `pkcs11t.h` appearing before constants in `pkcs11n.h`. - This program currently parses only parenthesis in a token's value, but not curly braces or square braces; the latter two shouldn't be present in most numeric types. Any failure to parse as a numeric type is a parse error which fails the script. For more information about this script, please refer to the comments therein. ## Java Test Included in the test suite when run on a JDK8 machine is a test called [`TestPKCS11Constants`](../src/test/java/org/mozilla/jss/tests/TestPKCS11Constants.java). This uses reflection to compare the values of the PKCS11Constants.java provided by JSS and the version provided by Sun, reporting constants in four categories: 1. Those which are "OK", i.e., present in both Sun and JSS with the same value. 2. Those which are "JSS only", i.e., the constant name does not exist in the Sun distribution. These are not treated as errors. 3. Those which are "Sun only", i.e., the constant name does not exist in the JSS distribution. These are not treated as errors. 4. Those which are "not OK", i.e., present in both Sun and JSS but with different values associated to them. This is not an error. Information about all constants is written to stdout during testing; please manually review the "JSS only" and "Sun only" cases to see if any results are unexpected. jss-5.0.0/docs/repo_archive.md000066400000000000000000000016071412550063600162410ustar00rootroot00000000000000# JSS Archive At the time of migration to GitHub, JSS had collected a significant number of branches. Because these branches may be of historical importance, it has been decided to archive them in a separate repository. This allows us to prune the main repository while persisting this information. For more information on this decision, please refer to the [RFC](https://pagure.io/jss/issue/25). To view the JSS archive, navigate to the [`jss-archive`](https://github.com/dogtagpki/jss-archive) repository. Because this repository has the same commits as the `jss` repository, it is possible to use both together: ``` cd /path/to/jss git remote add jss-archive https://github.com/dogtagpki/jss-archive git fetch jss-archive ``` At this point, all prior branches and tags will be synchronized with your current repository. To checkout a retired branch: ``` git checkout jss-archive/BRANCH_NAME ``` jss-5.0.0/docs/usage/000077500000000000000000000000001412550063600143515ustar00rootroot00000000000000jss-5.0.0/docs/usage/benchmarksslsocket.md000066400000000000000000000156251412550063600205710ustar00rootroot00000000000000# Usage This benchmark is a server-side SSLSocket benchmark for use with clients which measure performance. This benchmark does not, itself, make any performance measurements. For instance: ```bash $ ./run_test.sh org.mozilla.jss.tests.BenchmarkSSLSocket JSS.legacy Server_RSA 8443 1024 & $ siege -c 100 -b -t 5m https://localhost:8443 $ kill %1 ``` There are three supported SSLSocket implementations: 1. `org.mozilla.jss.ssl.SSLSocket`, JSS's legacy implementation name: `JSS.legacy` 2. `org.mozilla.jss.ssl.javax.JSSSocket`, JSS's new javax implementation name: `JSS.SSLSocket` 3. `sun.security`'s `SSLSocketImpl` from the current JDK. name: `SunJSSE.SSLSocket` It is suggested to disable all logging (for instance, via: `truncate -s 0 tools/logging.properties`) in order have reproducible results. This class takes four arguments when invoked: 1. The name of the implementation to benchmark, see above. 2. An alias of the certificate or path to a PKCS#12 file. Only SunJSSE accepts a PKCS#12 as path -- the two JSS based SSLSocket implementations will utilize a nickname instead. 3. The port to listen on. 4. The size of the HTTP message to fake. Note that, when utilizing a JSS provider, JSS must be loaded via a java.security. When utilizing SunJSSE, for best results, do not load JSS via java.security. It is suggested to use `run_test.sh` from the `build/` directory for executing this utility. # Past Performance ## `JSSEngineReferenceImpl` These are the results from siege [0] as run via: ```bash $ siege -c 100 -b -t 5m https://localhost:8443 ``` with the benchmarker set to send a faked 1024-byte message: ```bash $ ./run_test.sh org.mozilla.jss.tests.BenchmarkSSLSocket JSS.legacy Server_RSA 8443 1024 ``` The server certificate is 4096-bits. The selection of cipher suite and protocol is left at their defaults. This is on a Lenovo Thinkpad P50 with an `Intel(R) Core(TM) i7-6820HQ CPU @ 2.70GHz` processor and 32GB of RAM. Each request gets spun off and handled by a new thread. Using the legacy `org.mozilla.jss.ssl.SSLSocket` (old NSS-based socket) memory stays stable and under ~1-2% of total memory: ```json { "transactions": 98588, "availability": 100.00, "elapsed_time": 299.43, "data_transferred": 96.28, "response_time": 0.30, "transaction_rate": 329.25, "throughput": 0.32, "concurrency": 99.80, "successful_transactions": 98588, "failed_transactions": 0, "longest_transaction": 29.94, "shortest_transaction": 0.04 } ``` Using `javax.net.ssl.SSLSocket` provided by SunJSSE (but with JSS crypto and potentially random) and stays under 1-2% of total memory: ```json { "transactions": 2417, "availability": 100.00, "elapsed_time": 299.36, "data_transferred": 2.36, "response_time": 12.12, "transaction_rate": 8.07, "throughput": 0.01, "concurrency": 97.82, "successful_transactions": 2417, "failed_transactions": 0, "longest_transaction": 21.27, "shortest_transaction": 1.63 } ``` **Note** that the above option was removed from the benchmark utility as it was significantly slower. Using `javax.net.ssl.SSLSocket` provided by SunJSSE (without JSS crypto, via exporting to PKCS12 file) and stays under 8% of total memory: ```json { "transactions": 93168, "availability": 100.00, "elapsed_time": 299.92, "data_transferred": 90.98, "response_time": 0.32, "transaction_rate": 310.64, "throughput": 0.30, "concurrency": 99.51, "successful_transactions": 93168, "failed_transactions": 2, "longest_transaction": 15.81, "shortest_transaction": 0.02 } ``` And `javax.net.ssl.SSLSocket` provided by Mozilla-JSS, backed by our slow JSSEngine (proposed for 8.3) -- memory grows to ~35% of total, which suggests there's also at least one memory leak still... ```json { "transactions": 87768, "availability": 100.00, "elapsed_time": 299.08, "data_transferred": 85.71, "response_time": 0.34, "transaction_rate": 293.46, "throughput": 0.29, "concurrency": 99.60, "successful_transactions": 87768, "failed_transactions": 1, "longest_transaction": 16.05, "shortest_transaction": 0.08 } ``` Prior to jss-pr#553 (commit 1bd646a45613d16f18f28c641381f680ba1df319), the performance of Mozilla-JSS's `SSLSocket` was similar to `javax.net.ssl.SSLSoket` using `Mozilla-JSS` for primitives: ```json { "transactions": 1551, "availability": 85.98, "elapsed_time": 299.53, "data_transferred": 1.51, "response_time": 13.02, "transaction_rate": 5.18, "throughput": 0.01, "concurrency": 67.42, "successful_transactions": 1551, "failed_transactions": 253, "longest_transaction": 78.01, "shortest_transaction": 0.50 } ``` And for comparison, `nginx-1.18.0-1.fc32.x86_64`, using the same cert from above (admittedly, it uses OpenSSL and an `epoll` framework) and same `siege` output: ```json { "transactions": 214725, "availability": 100.00, "elapsed_time": 299.05, "data_transferred": 209.90, "response_time": 0.14, "transaction_rate": 718.02, "throughput": 0.70, "concurrency": 99.40, "successful_transactions": 214725, "failed_transactions": 0, "longest_transaction": 0.37, "shortest_transaction": 0.07 } ``` jss-5.0.0/docs/usage/capabilities_list.md000066400000000000000000000052261412550063600203640ustar00rootroot00000000000000CapabilitiesList ======================================== Overview ======================================== **CapabilitiesList** is a Java application to list the capabilities of the "Mozilla-JSS" provider and other installed providers. It does it in two fashions brief and verbose. It lets JSS contributors see what features the JDK implements (at different versions) and see what else we'd need to add in, to reach compatibility. Since we're attempting to be a default crypto provider, it would be nice to ensure we're mostly close to what the JDK provides. Hopefully other packages written to the JDK provider can have similar algorithms available under JSS and behave well. Large gaps in coverage are likely an issue such as [#341](https://github.com/dogtagpki/jss/issues/341) and [#242](https://github.com/dogtagpki/jss/issues/242). Usage ======================================== First build jss according to the instructions here [README](../../README.md) You should see in the build directory tests_jss.jar which is what contains the application along with the regular tests. From the `jss/build` directory execute ./run_test.sh org.mozilla.jss.tests.CapabilitiesList and you should see a `listings` directory Running `tree listings` should produce something like listings/ ├── brief │ ├── Capabilities4JdkSASL.txt │ ├── Capabilities4Mozilla-JSS.txt │ ├── Capabilities4SunJCE.txt │ ├── Capabilities4SunJSSE.txt │ ├── Capabilities4SunPKCS11.txt │ ├── Capabilities4SunRsaSign.txt │ └── Capabilities4SUN.txt └── verbose ├── Capabilities4JdkSASL.txt ├── Capabilities4Mozilla-JSS.txt ├── Capabilities4SunJCE.txt ├── Capabilities4SunJSSE.txt ├── Capabilities4SunPKCS11.txt ├── Capabilities4SunRsaSign.txt └── Capabilities4SUN.txt Here is a brief clip of Capabilities4Mozilla-JSS.txt AlgorithmParameters : IvAlgorithmParameters AlgorithmParameters : RC2AlgorithmParameters AlgorithmParameters : RSAPSSAlgorithmParameters Cipher : AES Cipher : DES Cipher : DESede Alias: Cipher.DES3 Cipher : RC2 Cipher : RC4 Cipher : RSA KeyFactory : DSA KeyFactory : EC KeyFactory : RSA KeyGenerator : AES KeyGenerator : DES KeyGenerator : DESede Alias: KeyGenerator.DES3 KeyGenerator : HmacSHA1 ... ommitted ... KeyGenerator : HmacSHA512 KeyGenerator : KbkdfCounter Alias: KeyGenerator.SP800-108-Counter ... ommitted ... Notice that the `Alias:` lines have extra indentation which makes it easier to compare against the other providers. jss-5.0.0/docs/usage/cryptomanager.md000066400000000000000000000160761412550063600175600ustar00rootroot00000000000000# `CryptoManager` ## Design ### `CryptoManager`, `JSSProvider`, and `JSSLoader` interactions `CryptoManager` is the central singleton of JSS. It controls access to the NSS database and an instance (available to developers via the `CryptoManager.getInstance()` call) signals that both JSS and NSS are properly initialized. The existing relationship between `CryptoManager` and `JSSProvider` is that a single `CryptoManager` instance has a single `JSSProvider` instance, and moreso that the reverse is also true: the `JSSProvider` instance has a single `CryptoManager` instance. Currently the code assumes that there is only ever one `CryptoManager` instance, making both singletons. _Aside:_ > Future work could be done to enable either multiple `CryptoManager` instances > with separate NSS DBs, or to enable multiple `JSSProvider` instances to > reference one or more `CryptoManager` instances during normal operation. > This currently will require significant restructuring as many internal > provider methods (such as `Cipher`, `Signature` and others) get the global > singleton instance directly (via `CryptoManager.getInstance()`). > > Additionally, NSS provides the option to load multiple NSS DBs into the > current instance, which might satisfy the use case of multiple > `CryptoManager` instances as well. --- However, the existence of `JSSLoader` and subsequently allowing JSS to load via the standard provider `java.security` file has complicated this slightly, to enable new use cases for JSS. Take the following code snippet for instance: ```java import org.mozilla.jss.CryptoManager; public class Example { public static void main(String[] args) throws Exception { CryptoManager cm = CryptoManager.getInstance(); // Additional code elided. } } ``` When used with JSS loaded via `java.security` override, the developer would rightly expect that JSS will load first, allowing `CryptoManager` to return a valid instance. In order to facilitate this however, when the internal `instance` field is `NULL`, JSS must first try to load itself via the Provider interface. That is, it needs to do something akin to: ```java java.security.Provider p = Security.getProvider("Mozilla-JSS"); ``` in order to force Java to attempt to load JSS. Any equivalent call into the Java security interface would also suffice (such as `Signature.getInstance(algo, "Mozilla-JSS")`), but this call limits the size of the resulting object and makes clear the intent. _Aside:_ > This becomes a touch tricky though. In particular, `CryptoManager.instance` > access is usually locked, to prevent modification by one thread while > another is reading it. This is locked at the class level (via a > `synchronized (CryptoManager.class)` statement explicitly or implicitly > in the synchronized `initialize()` method). So, inside `getInstance()`, we > explicitly acquire the lock to check the value of `instance`, release it for > the provider call -- in case it loads JSS from the provider interface -- > and then explicitly re-acquire it to return the value. This should help to > prevent race conditions and returning a partially-initialized > `CryptoManager` instance before it is fully ready. Otherwise, the call will fail and we'd require code changes, such as: ```java import java.security.*; import org.mozilla.jss.CryptoManager; public class Example { public static void main(String[] args) throws Exception { Provider p = Security.getProvider("Mozilla-JSS"); CryptoManager cm = CryptoManager.getInstance(); // Additional code elided. } } ``` in order for this to work. --- `CryptoManager` hasn't historically exposed a check to see if it is currently initialized. Under earlier `JSSProvider` code, it would use `CryptoManager.getInstance() != null` as the check for whether or not `CryptoManager` was initialized. Consider the original code above: this leads to the interesting recursion: - `CryptoManager.getInstance()` sees that `instance` is `NULL`, triggering `JSSProvider` to load. - `JSSProvider` -- while checking whether it needs to load -- would in turn call `CryptoManager.getInstance()` again. - Because `CryptoManager.getInstance()` again sees that `instance is `NULL` it will try to load `JSSProvider` again. Preventing us from infinite recursion though, `Security.getProvider(...)` will return `NULL`, and we'll successfully indicate that we need to load `JSSProvider`. The net result is that we successfully load only a single `JSSProvider` instance. However, when running with security debug flags (such as `-Djava.security.debug=all`), the Provider loader would report the recursion as a stack trace such as: ```java ProviderConfig: Loading provider: org.mozilla.jss.JSSProvider('/home/ascheel/GitHub/sandbox/jss/build/config/jss.cfg') ProviderConfig: Recursion loading provider: org.mozilla.jss.JSSProvider('/home/ascheel/GitHub/sandbox/jss/build/config/jss.cfg') java.lang.Exception: Call trace at sun.security.jca.ProviderConfig.getProvider(ProviderConfig.java:180) at sun.security.jca.ProviderList.getProvider(ProviderList.java:233) at sun.security.jca.ProviderList.getIndex(ProviderList.java:263) at sun.security.jca.ProviderList.getProviderConfig(ProviderList.java:247) at sun.security.jca.ProviderList.getProvider(ProviderList.java:253) at java.security.Security.getProvider(Security.java:503) at org.mozilla.jss.CryptoManager.getInstance(CryptoManager.java:368) at org.mozilla.jss.JSSLoader.loaded(JSSLoader.java:86) at org.mozilla.jss.JSSLoader.init(JSSLoader.java:111) at org.mozilla.jss.JSSLoader.init(JSSLoader.java:103) at org.mozilla.jss.JSSProvider.configure(JSSProvider.java:68) at org.mozilla.jss.JSSProvider.(JSSProvider.java:47) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at sun.security.jca.ProviderConfig$2.run(ProviderConfig.java:224) at sun.security.jca.ProviderConfig$2.run(ProviderConfig.java:206) at java.security.AccessController.doPrivileged(Native Method) at sun.security.jca.ProviderConfig.doLoadProvider(ProviderConfig.java:206) at sun.security.jca.ProviderConfig.getProvider(ProviderConfig.java:187) at sun.security.jca.ProviderList.getProvider(ProviderList.java:233) at sun.security.jca.ProviderList.getIndex(ProviderList.java:263) at sun.security.jca.ProviderList.getProviderConfig(ProviderList.java:247) at sun.security.jca.ProviderList.getProvider(ProviderList.java:253) at java.security.Security.getProvider(Security.java:503) at org.mozilla.jss.CryptoManager.getInstance(CryptoManager.java:368) at org.mozilla.jss.tests.SymKeyGen.(SymKeyGen.java:210) at org.mozilla.jss.tests.SymKeyGen.main(SymKeyGen.java:266) ``` By introducing a `isInitialized()` method, we can use a proper check that doesn't invoke this recursion, namely `instance == null` directly in the `CryptoManager` instance. jss-5.0.0/docs/usage/jssengine.md000066400000000000000000000573621412550063600166750ustar00rootroot00000000000000# `JSSEngine` - Documentation ## About `JSSEngine` `JSSEngine` is JSS's implementation of the [`SSLEngine`][javax.ssl-engine] contract for non-blocking TLS. Unlike the `SunJSSE` provider's `SSLEngine` (when using the `SunPKCS11-NSS` provider for primitives), this is built directly on NSS's high-level SSL module. This is better for FIPS compliance and HSM support (as keys never leave the NSS cryptographic module) and also means that we don't need to reimplement the underlying state machine. This approach is consistent with our [JSS `SSLSocket`][jss.ssl-socket]. ## Using `JSSEngine` There are two ways to use the `JSSEngine`: via the JCA Provider interface, or constructing a `JSSEngine` instance directly. The former method is preferred out of the two. Please refer to the [`JSSEngine` test cases][jss.jssengine.tests] or to the [Oracle `SSLEngine` demo][oracle.sslengine.demo] for information on using it. Usually a `SSLEngine` instance is asked by an external API (e.g., Tomcat) or used inside a `SSLSocket` implementation, such as the `SSLSocket` implementation provided by `Mozilla-JSS`'s SSLContext`. ### Via the JSSProvider This is the preferred way of using the `JSSEngine`. To construct a new [`SSLEngine`][javax.ssl-engine] instance, first get `Mozilla-JSS`'s [`SSLContext`][javax.ssl-context]: ```java // First get the necessary KeyManagers and TrustManagers. Note that // selecting KeyManagers and TrustManagers is discussed more below. KeyManagerFactory kmf = KeyManagerFactory.getInstance("NssX509", "Mozilla-JSS"); KeyManager[] kms = kmf.getKeyManagers(); TrustManagerFactory tmf = TrustManagerFactory.getInstance("NssX509", "Mozilla-JSS"); TrustManager[] tms = tmf.getTrustManagers(); // Then, initialize the SSLContext with the above information. Note that // we don't utilize the SecureRandom parameter, as NSS internally handles // generating random numbers for us. SSLContext ctx = SSLContext.getInstance("TLS", "Mozilla-JSS"); ctx.init(kms, tms, null); // If we don't have any peer host/port information, use this form: SSLEngine engine = ctx.createSSLEngine(); // Otherwise, use this form: SSLEngine engine = ctx.createSSLEngine(peerHost, peerPort); ``` The [`SSLContext`][javax.ssl-context] also provides methods helpful for configuring the [`SSLEngine`][javax.ssl-engine]. These are `SSLContext.getDefaultSSLParameters()` and `SSLContext.getSupportedSSLParameters()`. These provide the default parameters used by the SSLEngine and all supported SSLParameters, respectively. For more information about configuring the `JSSEngine`, see the section below. Note that the `Mozilla-JSS` provider's `SSLContext` instance also provides methods for creating `SSLSocket` factories which conform to the same `javax.net.ssl` interfaces. These sockets utilize the `JSSEngine` internally and expose many of the same configuration methods under the `JSSSocket` class namespace. The results of these factories can be directly cast to `JSSSocket` or `JSSServerSocket` as appropriate. ### Direct Utilization This is the less preferred way of using the `JSSEngine`. This requires understanding the class layout of `JSSEngine`. See the section below for more information. First, get an instance of `JSSEngine`: ```java /* If no session resumption hints are provided: */ // JSSEngine engine = new JSSEngine<$Impl>(); /* If we already know the peer's host and port: */ // String peerHost; // int peerPort; // JSSEngine engine = new JSSEngine<$Impl>(peerHost, peerPort); /* Or laastly, if we know the peer's host and port, and want to set * a certificate and key to use for our side of the connection: */ // X509Certificate localCert; // PrivateKey localKey; JSSEngine engine = new JSSEngine<$Impl>(peerHost, peerPort, localCert, localKey); ``` Replace `JSSEngine<$Impl>` with one of the implementing classes below. Then, continue with configuring the `JSSEngine` below. ### Configuring the `JSSEngine` Configuring the `JSSEngine` is a multi-step process. Below are common configuration options grouped into categories. #### Choosing Handshake Side Configuring which side of the handshake this `JSSEngine` will use occurs via a call to `setUseClientMode(boolean mode)`. When `mode` is `true`, this engine will handshake as if it was the client. Otherwise, this engine will handshake as a server. Note that calling `setUseClientMode(...)` after the handshake has started (either via calling `beginHandshake(...)`, `wrap(...)`, or `unwrap(...)`) isn't supported. Checking the current mode can be done via `getUseClientMode(...)`. #### Choosing Key Material Key material can be chosen in several ways. In every scenario, a JSSKeyManager instance needs to be passed to the JSSEngine: ```java // JSSEngine inst; inst.setKeyManager(new JSSKeyManager()); ``` For direct selection of key from an existing instance, call `setKeyMaterials`: ```java // JSSEngine inst; inst.setKeyMaterials(myPK11Cert, myPK11PrivKey); ``` Note that these must be instances of [`PK11Cert`][jss.pk11-cert] and [`PK11PrivKey`][jss.pk11-privkey] respectively. These can be obtained from the [`CryptoManager`][jss.cryptomanager] and casting `X509Certificate` to `PK11Cert` and `PrivateKey` to `PK11PrivKey`. For selection of a key via an alias in the certificate database, call `setCertFromAlias`: ```java // JSSEngine inst; inst.setCertFromAlias("server-cert-alias"); ``` Lastly, key material could've been provided when the `JSSEngine` was constructed; see the section on direct utilization above. Note that SNI support isn't yet added so the key selection must occur prior to the initial handshake. #### Choosing TLS protocol version There are two ways to choose TLS protocol version. The first is via the Java Provider interface, selecting the TLS version directly. The `Mozilla-JSS` provider understands the following aliases: - `SSL` and `TLS`, enabling any allowed SSL and TLS protocol version, - `TLSv1.1` to enable only TLS version 1.1 by default, - `TLSv1.2` to enable only TLS version 1.2 by default, and - `TLSv1.3` to enable only TLS version 1.3 by default. Alternatively, the standard `SSLEngine` configuration method of passing a list of protocols to `setEnabledProtocols` is also allowed. Note that this will override any value passed via the Provider interface. Additionally, due to restrictions in NSS, a contiguous range of protocols will be enabled. For example, the following call: ```java // SSLEngine inst; inst.setEnabledProtocols(new String[] { "TLSv1.1", "TLSv1.3" }); ``` will enable TLSv1.1, TLSv1.2, and TLSv1.3. Alternative methods are available that take JSS standard `SSLVersion` and `SSLVersionRange` values as parameters; see the `JSSEngine` javadoc for more information. #### Choosing Cipher Suite Configuring cipher suites is performed using the standard `SSLEngine` configuration method of passing a list of cipher suites to `setEnabledCipherSuites`. We filter the list of passed cipher suites to only those allowed by local policy. For example: ```java // SSLEngine inst; inst.setEnabledCipherSuites(new String[] { "TLS_AES_128_GCM_SHA256" }); ``` will enable only a single TLSv1.3 cipher suite. Alternative methods are available that take JSS standard `SSLCipher` values as parameters; see the `JSSEngine` javadoc for more information. #### Using `JSSParameters` `JSSParameters` largely aligns with `SSLParameters` except that it allows two important introductions: 1. Selection of key material, like above. See the javadocs on `JSSParameters` for more information. 2. Setting the peer's hostname, for use with validation of certificates. This allows us to tie into NSS's hostname verification directly, instead of responding after the fact by closing the connection. Generally, using `SSLParameters` should be sufficient for most applications. Two exceptions are when we wish to explicitly select key material (e.g., from a certificate nickname) or when using NSS for SSL hostname validation. #### Session Control The `JSSEngine` lacks many of the session control functions other `SSLEngine` implementations might have. In particular, we: - Always enable session resumption; this cannot be disabled. - Allow forced expiration of a session as long as the `SSLEngine`'s connection isn't yet closed. - Report accurate creation/expiration/last accessed times. However, other features of sessions (such as configuring location and size of the session cache) aren't yet configurable. ## Design of the `JSSEngine` ### Class Structuring The below is a digram showing the structure of `JSSEngine` classes: ----------- | JSSEngine |------------------------- ----------- \ / \ \ ------------------------ ------------------------ ------ | JSSEngineReferenceImpl | | JSSEngineOptimizedImpl | | .... | ------------------------ ------------------------ ------ `JSSEngine` is an abstract class extending [`SSLEngine`][javax.ssl-engine]. This class implements some of the boilerplate required for implementing a `SSLEngine`, including handling cipher and protocol version configuration. Individual implementations implement `wrap`, `unwrap`, and whatever specifics are necessary to initialize and release the SSL-backed `PRFileDesc`. We expect two primary implementations: - `JSSEngineReferenceImpl`, a reference implementation with more logging and debugging statements. This also includes port-based debugging, so situations where a `SSLEngine` isn't writing to the network can still be tracked and analyzed in Wireshark. Each call to `wrap` or `unwrap` makes several JNI calls, incurring lots of overhead. - `JSSEngineOptimizedImpl`, an optimized, production-ready implementation. This one is harder to debug due to fewer logging statements, but does improve performance significantly with fewer JNI calls. ### Non-Blocking IO In order to implement `wrap` and `unwrap` on the SSLEngine, we use NSPR sockets configured in non-blocking mode. Data is held in buffers rather than being written to the network; in this way, data is passed from a `unwrap` call to `NSPR` so that `NSS` can decrypt the wire data, with the result being returned from `unwrap`. This is implemented as follows: NSPR introduces a platform-independent abstraction over C's file descriptors (usually an `int`) in the form of the `PRFileDesc` structure. This is layer-able, allowing us to write our own and then have it be accepted by NSS's SSL `PRFileDesc` implementation as the underlying transport. Our `PRFileDesc` is called `BufferPRFD` and lives next to the `JSSEngine` implementation in `org/mozilla/jss/ssl/javax`. Each `BufferPRFD` is backed by two `j_buffer` instances (located adjacent). A `j_buffer` is a circular ring buffer optimized to allow efficient access to the underlying data. One `j_buffer` is dedicated to the read end of this `BufferPRFD` (the data that is returned when `recv(...)` is called); the other is dedicated to the write end of this `BufferPRFD` (the data that is waiting to get sent on the wire). Note that the `j_buffer` instances exist independently from the `BufferPRFD`: the `JSSEngine` itself creates the `j_buffer`s and hands them to the `BufferPRFD` to use, because it too needs to be able to read from them. This forms the following data path once the initial handshake is complete: ------------- | Application | ------------- | ^ app | | wire SSLEngine.wrap(data, result) data | | data V | ----------- jb_read(write, result) ---------- | JSSEngine | <-------------------- | j_buffer | ----------- ---------- | ^ | PR.Write(ssl_fd, data) | jb_write(write, enc_data) v | ----- ----------- | NSS | -----------------------> | PRFileDesc| ----- ----------- PR.Write(buffer_fd, enc_data) The application creates application data it wants to send to its peer. It invokes `SSLEngine.wrap(data, result)`, where `data` is the application data and `result` is an empty buffer large enough to store the resulting wire data. The `JSSEngine` passes this data (via a call to `PR.Write`) to NSS along the SSL `PRFileDesc` (`ssl_fd`) associated with this `JSSEngine`. NSS encrypts this data and writes it to the underlying `BufferPRFD`. If the `BufferPRFD` has sufficient space in its write `j_buffer`, it can accept all the data. This occurs in the `PR.Write` call on the `BufferPRFD`. At this point, the call stack returns to `JSSEngine.wrap(...)`. When it sees that there is data in the underlying write `j_buffer`, `JSSEngine` reads from the write `j_buffer`, thereby freeing space in it for the next PR.Write(...) invocation, and adds this to the application's `result` (wire data) buffer. A similar process (with the bottom loop reversed) occurs for the application decrypting data from its peer. In this case, encrypted wire data is written to the read `j_buffer`, a call to `jb_read(read)` from `PR.Read(buffer_fd)` occurs inside NSS when a call to `PR.Read(ssl_fd)` is made from the SSLEngine. The unencrypted result is then passed to the caller of `SSLEngine.unwrap(...)`. ### Handshaking The data flow described above in the section on Non-Blocking IO applies to the initial TLS Handshake as well, except there's no initial application data and the `JSSEngine` doesn't call `PR.Write(...)`. [TLSv1.2][rfc.tls-1.2] and [TLSv1.3][rfc.tls-1.3] both have state machines at the core of their handshake mechanism. However, NSS doesn't expose the current state of the handshake or whether or not we can continue without any additional information from the remote peer. When a `JSSEngine` is initialized, the first thing it expects to do is begin a handshake with a peer. The TLS handshake begins with the client sending a Client Hello message to the server. When the SSLEngine is initialized as a client, it sets the handshake state to `NEED_WRAP` (so we can send the outbound Client Hello); when initialized as a server, it gets set to `NEED_UNWRAP` so we can receive the inbound Client Hello from the peer. When `SSL.ForceHandshake` is called, NSS steps the internal state machine. This results in a call to `PR.Read(...)` to read any inbound data, and if this client needs to write a message, a call to `PR.Write(...)`. In this way, all inbound data on the wire is consumed, and if a message needs to be transmitted, we can check the amount of data in the write `j_buffer`. This gives us the following heuristic for handshaking: 1. Get the Security Status prior to handshaking via `SSL.SecurityStatus(...)` 2. Perform `SSL.ForceHandshake(...)` 3. Get the Security Status again 4. Determine our next step: - If we need to send data to the client (and this wasn't a `wrap` call), change status to `NEED_WRAP` - If the handshake status reports security is on (and there is no more data to send in a `wrap` call!), we've just finished handshaking and have sent the last commit message, so change status to `FINISHED`. - If we have no more data to read from the client (and no outbound data either), we assume we need more data from the client so we change the status to `NEED_UNWRAP`. - Otherwise, we keep the status the same. We increment a unknown state counter -- this flips the value from its previous value to the opposite of what it was (e.g., `NEED_WRAP` to `NEED_UNWRAP`). This helps to ensure we don't ever get stuck. This heuristic is wrapped in `updateHandshakeState`, which is called from `wrap`, `unwrap`, and `getHandshakeStatus`; the unknown state counter gets incremented in all three places. ### Post-Handshake Auth (PHA) and Re-Handshaking Prior to TLS 1.3, clients and servers could initiate another handshake, allowing clients the chance to specify authentication that wasn't provided at the initial handshake. This also allowed the client and server to negotiate a new key. Because this poses a [security risk][rfc.tls-renegotiation], a TLS extension modifies the behavior to improve security. However, this behavior was removed in TLS 1.3 and replaced with two separate steps: one mechanism to provide authentication post-handshake and another to rekey the handshake. By default, renegotiation and PHA support are both enabled for a `JSSEngine`. In order to issue such a renegotiation, change the status of client authentication after the initial handshake: ```java // SSLEngine inst; inst.setNeedClientAuth(true); ``` Then call `beginHandshake()` in order to re-handshake: ```java inst.beginHandshake(); ``` Complete a handshake as usual. Note that this will detect if TLS 1.3 or a previous version was negotiated and choose between a rehandshaking and PHA as appropriate for the selected TLS version. #### Disabling Post-Handshake Auth (PHA) In order to disable PHA support, cast `SSLEngine` to a `JSSEngine` instance prior to the initial handshake and remove the PHA configuration option, `SSL.ENABLE_POST_HANDSHAKE_AUTH` or set it to `0` to disable it: ```java import org.mozilla.jss.ssl.javax.JSSEngine; import org.mozilla.jss.nss.SSL; // JSSEngine inst; inst.addConfiguration(SSL.ENABLE_POST_HANDSHAKE_AUTH, 0); ``` Note that this must be done before `beginHandshake()`, `wrap()`, or `unwrap()` is called. #### Disabling Re-Handshaking In order to disable or configure secure renegotiation, the following configuration options can be modified: - `SSL.ENABLE_RENEGOTATION` - set to `SSL.RENEGOTIATE_NEVER` to disable all attempts at renegotation; set to `SSL.RENEGOTIATE_UNRESTRICTED` to always renegotiation even in unsafe scenarios; set to `SSL.RENEGOTIATE_REQUIRES_XTN` to only allow secure renegotiation; set to `SSL.RENEGOTIATE_TRANSITIONAL` to require the renegotiation extension when this is a server connection, but allowing clients to handshake with vulnerable servers. - `SSL.REQUIRE_SAFE_NEGOTIATION` - set to `1` by default, can be set to `0` to enable unsafe renegotiation. - `SSL.ENABLE_FALLBACK_SCSV` - set to `1` by default to send the fallback `SCSV` pseudo-ciphersuite; can be set to `0` to disable sending the option. For example, to disable renegotiation completely: ```java import org.mozilla.jss.ssl.javax.JSSEngine; import org.mozilla.jss.nss.SSL; // JSSEngine inst; inst.addConfiguration(SSL.ENABLE_RENEGOTATION, SSL.RENEGOTIATE_NEVER); ``` Note that this must be done before `beginHandshake()`, `wrap()`, or `unwrap()` or called. ### SSL Alert Handling NSS exposes access to protocol-level alerts via the two callback functions, `SSL_AlertReceivedCallback` (for when an alert was received from the remote peer) and `SSL_AlertSentCallback` (for when NSS sends an alert to the remote peer). When attempting non-blocking IO, there's a weird quirk about how these callbacks function: the only execute when a NSPR `PR_Read(...)` or `PR_Write(...)` call executes on the SSL `PRFileDesc`. In particular, it isn't sufficient to simply call `SSL_ForceHandshake(...)`! The callbacks strictly occur when the alerts are on the wire, and don't execute for future alerts we're expecting to send. This convolutes our exception handling slightly. JSS takes the following approach to handling SSL Alerts and exposing them to callers via exceptions: 1. `SSLFDProxy` contains separate queues of inbound and outbound `SSLAlert`s. 2. `checkSSLAlert` verifies whether or not a fatal alert was received and/or sent. 3. The first such fatal alert that was received or sent is converted into an `SSLException` instance; this is saved to the `JSSEngine`'s state and returned. 4. `updateHandshakeState()` checks to see if a SSL alert occurred prior to calling SSL_ForceHandshake(...)` -- if so, it does no work. 5. `wrap` and `unwrap` also check SSL alerts after all work is done. This ensures we always trigger a call into NSPR's `PR_Write(...)` or `PR_Read(...)`. 6. When an alert occurs in `unwrap` (especially during a handshake), we make sure to set the state to `wrap` so our response (either the alert itself or our confirmation of it) is recorded. 7. Lastly, we make sure to throw an exception only once and not multiple times. ### `wrap`/`unwrap` with large Buffers While `SSLSession` indiciates the size of its internal buffers (via `SSLSession.getApplicationBufferSize()`), we might get `src` and `dst` buffers large enough to overflow our internal buffer multiple times. While we could indicate this via returning a short read (`bytesConsumed()` or `bytesProduced()` on `SSLEngineResult` from a `wrap` or `unwrap` respectively), this could make the application allocate multiple buffers or invoke `wrap()`/`unwrap()` multiple times. This overhead isn't necessary, as we can detect this ourselves within `JSSEngine`. For a `wrap()` call, there's two places data could be produced: in `updateHandshakeState()` when we're handshaing or in `writeData()`. There's only one place wire data is placed: `write_buf`. Because `write_buf` is limited to `BUFFER_SIZE` bytes, we could produce bytes (up to the capacity of `write_buf`), write them to `dst`, and then be able to produce more bytes. We stop when we are no longer producing or consuming any bytes. This leaves us with one extra invocation of `updateHandshakeState()`, `writeData()`, and reading from `write_buf`, but this is necessary to flush the internal NSS buffer. A similar description applies to `unwrap`. To accomplish handling large buffers, we simply wrap the core body of `wrap()` and `unwrap()` in a loop, stopping when no more data is being produced and consumed. This will stop because: the input and output buffers we're given are bounded in size and if an exception occurs, after writting the appropriate alert to the wire, NSS will quit reading/writing data. This means these loops are bound to terminate eventually. ### Future Improvements Currently we've only implemented the `JSSEngineReferenceImpl`; the optimized implementation still needs to be written. In particular, the performance of multiple JNI calls per step (`wrap` or `unwrap`) needs to be evaluated. We could replace this with a copy of the contents of the underlying ByteBuffer, perform a PR_Read or PR_Write operation, and then (in the event of a write), copy the modified data back. This would give us better performance for large buffers. We only have a single `JSSKeyManager` that doesn't understand SNI; we should make sure we support SNI from a client and server perspective. We need to make sure we can interact with external (non-JSS) [`X509TrustManager`s](javax.x09trustmanager) and use them to validate the peer's certificates. [javax.ssl-context]: https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/SSLContext.html "javax.net.ssl.SSLContext" [javax.ssl-engine]: https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/SSLEngine.html "javax.net.ssl.SSLEngine" [javax.x509trustmanager]: https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/X509TrustManager.html "javax.net.ssl.X509TrustManager" [jss.jssengine-tests]: https://github.com/dogtagpki/jss/blob/master/org/mozilla/jss/tests/TestSSLEngine.java "JSS SSLEngine tests" [jss.pk11-cert]: https://dogtagpki.github.io/jss/master/javadocs/org/mozilla/jss/pkcs11/PK11Cert.html "org.mozilla.jss.pkcs11.PK11Cert" [jss.pk11-privkey]: https://dogtagpki.github.io/jss/master/javadocs/org/mozilla/jss/pkcs11/PK11PrivKey.html "org.mozilla.jss.pkcs11.PK11PrivKey" [jss.ssl-socket]: https://dogtagpki.github.io/jss/master/javadocs/org/mozilla/jss/ssl/SSLSocket.html "org.mozilla.jss.ssl.SSLSocket" [oracle.sslengine.demo]: https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/samples/sslengine/SSLEngineSimpleDemo.java "Oracle SSLEngineSimpleDemo" [rfc.tls-1.2]: https://tools.ietf.org/html/rfc5246 "TLSv1.2 RFC 5246" [rfc.tls-renegotiation]: https://tools.ietf.org/html/rfc5746#section-5 [rfc.tls-1.3]: https://tools.ietf.org/html/rfc8446 "TLSv1.3 RFC 8446" jss-5.0.0/docs/usage/jssprovider.md000066400000000000000000000163171412550063600172550ustar00rootroot00000000000000# `Mozilla-JSS` Provider The `Mozilla-JSS` JCA-compatible Provider exposes most of the functionality of JSS to external packages. This interface is the recommend interface most developers should build against. However, once the dependencies are satisfied and JSS's native component is available to the JVM, we still have to load and initialize JSS. There are two routes to do this: 1. Via the `CryptoManager` interface, _and_ 2. Via `java.security`, directly loading the `JSSProvider`. ## Loading JSS via `CryptoManager` To load JSS from a `CryptoManager`, it is necessary to decide what level of configuration is necessary. If you're happy with the defaults, it is sufficient to only specify a NSS DB: ```java import org.mozilla.jss.CryptoManager; CryptoManager.initialize("/path/to/nss-db"); ``` At this point, JSS will be initialized and can be used. A password might be required, so see the section below for providing password callback handlers. Certain default values might not work in all situations. For instance, Candlepin expects other providers to be default, with the Mozilla-JSS provider being the least-preferred provider. To do this, they'd construct an `InitializationValues` instance and pass that to `CryptoManager.initialize(...)`: ```java import org.mozilla.jss.InitializationValues; InitializationValues ivs = new InitializationValues("/path/to/nss-db"); ivs.installJSSProviderFirst = false; CryptoManager.initialize(ivs); ``` See the section below on other options available to configure. ### `InitializationValues` options There are two constructors for `InitializationValues`: - Taking only a NSS DB directory. This was utilized above. - Taking a NSS DB directory, a prefix for the certificate database, a prefix for the key database, and the name of the secmod configuration. The latter is a more advanced use case and few individuals likely need to use it. For more information, see the corresponding NSS documentation on these values. Refer to the javadoc for `InitializationValues` for the supported parameters and their default values. ### `PasswordCallback` handlers In order to authenticate against a PKCS#11 token or to the internal certificate store, it is necessary to select a `PasswordCallback` handler. By default this is a console-based `PasswordCallback` handler. This prompts the user for the password via the Console. However, this is not appropriate in all scenarios. Developers are expected to extend and implement this as desired by their application. For example, to set a static `PasswordCallback` handler: ```java CryptoManager cm = CryptoManager.getInstance(); cm.setPasswordCallback(new Password("password".toCharArray())); ``` ## Loading JSS via `java.security` You can directly add the `JSSProvider` by adding it to the `java.security` file: ```properties security.provider. = org.mozilla.jss.JSSProvider /path/to/jss.cfg ``` There are two ways use this `java.security` file: by directly installing it to the system or by using `-Djava.security.properties=/path/to/file`. Note that two equals signs may be used, in which case the system configuration is ignored and fully overridden by this file. `JSSProvider` behaves like the `SunPKCS11-NSS` provider, requiring a configuration file to initialize JSS (and the `CryptoManager` object). `jss.cfg` takes the same `InitializationValues` parameters, except in a properties file format. ### JSS Config | property | Mapped To | |------------------------------------|--------------------------------------------------| | `jss.fips` | `InitializationValues.fipsMode` | | `jss.ocsp.enabled` | `InitializationValues.ocspCheckingEnabled` | | `jss.ocsp.policy` | `CryptoManager.setOCSPPolicy` | | `jss.ocsp.responder.cert_nickname` | `InitializationValues.ocspResponderCertNickname` | | `jss.ocsp.responder.url` | `InitializationValues.ocspResponderURL` | | `jss.password` | `CryptoManager.setPasswordCallback` | | `nss.config_dir` | `InitializationValues.configDir` | | `nss.cert_prefix` | `InitializationValues.certPrefix` | | `nss.cooperate` | `InitializationValues.cooperate` | | `nss.force_open` | `InitializationValues.forceOpen` | | `nss.java_only` | `InitializationValues.javaOnly` | | `nss.key_prefix` | `InitializationValues.keyPrefix` | | `nss.no_cert_db` | `InitializationValues.noCertDB` | | `nss.no_mod_db` | `InitializationValues.noModDB` | | `nss.no_pk11_finalize` | `InitializationValues.noPK11Finalize` | | `nss.no_root_init` | `InitializationValues.noRootInit` | | `nss.optimizeSpace` | `InitializationValues.optimizeSpace` | | `nss.pkix_verify` | `InitializationValues.pkixVerify` | | `nss.pk11_reload` | `InitializationValues.PK11Reload` | | `nss.pk11_thread_safe` | `InitializationValues.PK11ThreadSafe` | | `nss.read_only` | `InitializationValues.readOnly` | | `nss.secmod_name` | `InitializationValues.secmodName` | Note that the parameters `installJSSProvider`, `removeSunProvider`, and `installJSSProviderFirst` are ignored, as they can be controlled by directly manipulating the `java.security` file. ## Upgrading Old Code There are two paths to upgrade an older code base to a newer JSS version, using the JSSProvider interface: 1. Continue using `CryptoManager.initialize(...)` as before. This gives the local application the most control over the NSS DB path. No changes are required. 2. Switch to using `java.security`-based configuration (either via local policy with `-Djava.security.properties=/path` specified on the JVM command line or via system-wide policy by modifying the `$JAVA_HOME/conf/security/java.security` file). You can then remove the call to `CryptoManager.initialize(...)`. If this call is necessary for backwards-compatibility reasons (to support multiple JSS versions), it would be sufficient to check the value of `CryptoManager.getInstance(...)` before configuration: ```java try { cm = CryptoManager.getInstance(); } catch (NotInitializedException nie) { // Or throw this exception and provide instructions on how to // configure Mozilla-JSS in the java.security provider list. CryptoManager.initialize(...); cm = CryptoManager.getInstance(); } ``` This gives the user control over NSS DB path via modifying either of those two configuration files (or by providing a local override). Note that, between `java.security` and `CryptoManager.initialize()`, the latter takes precedence unless `CryptoManager` has already been initialized. This would happen if any java Security Provider calls are made or if `CryptoManager.getInstance()` is called. jss-5.0.0/docs/usage/kbkdf.md000066400000000000000000000354471412550063600157710ustar00rootroot00000000000000# KBKDF - Documentation ## About KBKDF KBKDF is defined in [NIST's SP800-108][sp800-108]: Key Based Key Derivation Functions. These are a collection of three KDFs based on MACing primitives: 1. Counter Mode in 5.1, 2. Feedback Mode in 5.2, and 3. Double Pipeline Mode in 5.3. These KDFs see usage in GlobalPlatform's Secure Channel Protocol 03, Kerberos, and other places. This KDF is implemented using [PKCS#11 v3.0][pkcs11-kbkdf]; refer to that document for additional information about using this KDF. ## Using KBKDF KBKDF usage is available from the `Mozilla-JSS` provider through the javax [`KeyGenerator`][key-generator] interface. There are two categories of KDF implementations: 1. `CKO_SECRET_KEY` keys, which cannot be extracted when the system is running in FIPS mode or when the key lives on an HSM, and 2. `CKO_DATA_OBJECT` keys, which can always be extract. The latter category is suitable for generating SCP03 challenges, but shouldn't be used with cryptographic operations. They have the "Data" suffix in the provider list. ### Constructing a KBKDF `KeyGenerator` To construct a KBKDF generator, get the instance via the provider interface: ```java import javax.crypto.KeyGenerator; KeyGenerator kg = KeyGenerator.getInstance("", "Mozilla-JSS"); ``` Where name depends on the choice of KBKDF: | KeyGenerator Name | Mode | Data | Parameter Class | |-------------------|----------|------|----------------------------------------------| | KbkdfCounter | Counter | no | [KBKDFCounterParams][kbkdf-counter-params] | | KbkdfCounterData | Counter | yes | [KBKDFCounterParams][kbkdf-counter-params] | | KbkdfFeedback | Feedback | no | [KBKDFFeedbackParams][kbkdf-feedback-params] | | KbkdfFeedbackData | Feedback | yes | [KBKDFFeedbackParams][kbkdf-feedback-params] | | KbkdfPipeline | Pipeline | no | [KBKDFPipelineParams][kbkdf-pipeline-params] | | KbkdfPipelineData | Pipeline | yes | [KBKDFPipelineParams][kbkdf-pipeline-params] | Various aliases for these KeyGenerators also exist; this allows for greater compatibility with existing systems which implement this KDF. These exist because the [Java Cryptography Architecture][jca] doesn't specify canonical names for these KDFs. ### Construct a KBKDF Parameter Specification Each KBKDF mode has its own parameter specification class, which must be used with a `KeyGenerator` of only that type. These classes are given in the above table and exist in the [`org.mozilla.jss.crypto`][jss-crypto] package. Each parameter spec derives from [`KBKDFParameterSpec`][kbkdf-spec]. These arguments are: | Name | Description | Modes | Setter | |-------------------------|--------------------------------------|----------|-----------------------------------------------------------------------------------------------------| | PRF | PRF used during KBKDF (HMAC or CMAC) | All | [`setPRF`][kbkdf-spec-set-prf] | | PRF Key | Key used for the PRF | All | [`setPRFKey`][kbkdf-spec-set-prf-key] | | Derived Algorithm | Algorithm of the primary derived key | All | [`setDerivedKeyAlgorithm`][kbkdf-spec-set-derived-algo] | | Key Size | Size of the primary derived key | All | [`setKeySize`][kbkdf-spec-set-key-size] | | Initial Value | Initial chaining value | Feedback | [`setInitialValue`][kbkdf-spec-set-iv] | | PRF Data Parameters | Parameters to control PRF input | All | [`setParameters`][kbkdf-spec-set-params] / [`addParameter`][kbkdf-spec-add-param] | | Additional Derived Keys | Additional keys to derive | All | [`setAdditionalDerivedKeys`][kbkdf-spec-set-keys] / [`addAdditionalDerivedKey`][kbkdf-spec-add-key] | Note: the methods and fields inherited from `NativeEnclosure` shouldn't be called by the KBKDF user during normal usage. #### Using Algorithms When using this KBKDF, both the PRF and the derived key's algorithm must be specified. In both cases, the user has a choice: either use the [PKCS#11 Constant][jss-pkcs11-constants] for the algorithm, or use the algorithm as specified in the [PKCS#11 Algorithm][jss-pkcs11-algorithm] enumeration. For example, the following are equivalent: ```java import org.mozilla.jss.pkcs11.PKCS11Constants; KBKDFCounterParams params = new KBDKFCounterParams(); params.setPRF(PKCS11Constants.CKM_AES_CMAC); ``` and ```java import org.mozilla.jss.crypto.PKCS11Algorithm; KBKDFCounterParams params = new KBKDFCounterParams(); params.setPRF(PKCS11Algorithm.CKM_AES_CMAC); ``` The latter gives a little more type safety and ensures that the specified algorithm is understood and implemented by JSS; otherwise, they're equivalent. #### Constructing KDF PRF Input Stream (Data) Parameters The core of PKCS#11's KBKDF implementation allows great flexibility in crafting the input stream to the underlying PRF invocation. This allows for a wide range of usages (including in SCP03), assuming some care is taken in ensuring the resulting KBKDF is secure from length extension attacks. See NIST S800-108 for more details regarding concerns. PKCS#11 v3.0 defines four types of input parameters: | Name | Description | |-----------------------------|------------------------------------------------------------| | KBKDFByteArrayParam | A static array of bytes to add to the PRF input stream | | KBKDFDKMLengthParam | A structure for encoding and calculating KDF output length | | KBKDFIterationVariableParam | Either an incrementing counter or a chaining value | | KBKDFOptionalCounterParam | (In Feedback and Pipeline Modes); an optional counter | Please refer to [section 2.42.2 Mechanism Parameters][pkcs11-kbkdf-params] for more information about correct usage of each parameter, how they correlate to names in NIST SP800-108, and with which KDF modes each parameter can be used. #### Deriving Additional Keys PKCS#11 v3.0 defines a way of extracting additional keys from the derived key material. See [section 2.42.6 Deriving Additional Keys][pkcs11-kbkdf-adk] for a comprehensive reference. The `CK_DERIVED_KEY` PKCS#11 structure is mirrored in the `KBKDFDerivedKey` class. Add PKCS#11 Attributes to the derived key, specify it in the KDF parameter. After `kg.generateKey(...)` has been called, `getKey(...)` will return the additional key. ### Example KBKDF Usage Putting this all together, the following is a short example of how to use the KBKDF to derive a single key for the SCP03 protocol. ```java public SymmetricKey kbkdfDeriveSCP03Key(SymmetricKey master, byte[] context, byte kdfConstant, int kdfOutputSizeBytes) { KeyGenerator kg = KeyGenerator.getInstance("KbkdfCounter", "Mozilla-JSS"); KBKDFCounterParams kcp = new KBKDFCounterParams(); kcp.setPRF(PKCS11Algorithm.CKM_AES_CMAC); kcp.setPRFKey(master); kcp.setKeySize(kdfOutputSizeBytes); byte[] label = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, kdfConstant }; kcp.addParameter(new KBKDFByteArrayParam(label)); byte[] separator = new byte[] { 0x00 }; kcp.addParameter(new KBKDFByteArrayParam(separator)); KBKDFDataParameter length = new KBKDFDKMLengthParam( // How to calculate the length, were there multiple derived keys. PKCS11Constants.CK_SP800_108_DKM_LENGTH_SUM_OF_SEGMENTS, // This length is big endian, so littleEndian == false. false, // How many bits to encode the length. SCP03 requires two bytes. 2*8 ); kcp.addParameter(length); KBKDFDataParameter counter = new KBKDFIterationVariableParam(false, 1*8); kcp.addParameter(counter); kcp.addParameter(new KBKDFByteArrayParam(context)); kcp.setDerivedKeyAlgorithm(PKCS11Algorithm.CKM_AES_CBC); kg.init(kcp); return kg.generateKey(); } ``` ## Design of KBKDF Unlike past key generation mechanisms, the `CKM_SP800_108_*` PKCS#11 mechs require extensive mechanism parameters. Under Java, these take the form of [`java.security.spec.AlgorithmParameterSpec`][alg-param-spec] implementations, but this leaves much to be desired when bridging the JNI gap. Our approach involved creating new extensions to the [`NativeProxy`][native-proxy] class: the [`NativeEnclosure`][native-enclosure]. Unlike a `NativeProxy` -- whose scope is implicit, a `NativeEnclosure` formalizes and specifies the exact scope of a C pointer. In particular, a `NativeProxy` instance could be created at any time by the JNI code; it is then given to Java to handle usage and cleanup. Additionally, a `NativeProxy` instance doesn't exist until it is created by C code. Contrasting with that, we need our parameter specifications to exist prior to the creation of the `NativeProxy` instance -- so we can populate them -- but we still need to capture the creation, use, and destruction of the underlying `NativeProxy`. This leads to two NativeEnclosure methods: - `acquireNativeResources(...)` to trigger an allocation of the `NativeProxy`, storing it on the `mPointer` member, and - `releaseNativeResources(...)` to trigger freeing it. These get wrapped in `open(...)` and `close(...)` respective, allowing us to implement the [`java.lang.AutoCloseable`][auto-close] class. This lets us use the parameters in the `KeyGenerator` as following: prior to the call (via JNI) to `PK11_DeriveKey(...)`. We call `open(...)` and handle any issues creating the `CK_SP800_108_KDF_PARAMS` or `CK_SP800_108_FEEDBACK_KDF_PARAMS` pointer. We pass this pointer directly to `PK11_DeriveKey(...)`, and when we're done, call `close(...)` to handle freeing it. Thus, we incur only a single allocation and free when we're ready to use the parameter, and the complexities of handling the JNI translation are hidden from the programmer wishing to use it. [alg-param-spec]: https://docs.oracle.com/javase/8/docs/api/java/security/spec/AlgorithmParameterSpec.html "java.security.spec.AlgorithmParameterSpec" [auto-close]: https://docs.oracle.com/javase/8/docs/api/java/lang/AutoCloseable.html "java.lang.AutoCloseable" [jca]: https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html "Java Cryptography Architecture Reference Guide" [jss-crypto]: https://dogtagpki.github.io/jss/master/javadocs/org/mozilla/jss/crypto/package-summary.html "org.mozilla.jss.crypto.*" [jss-pkcs11-algorithm]: https://dogtagpki.github.io/jss/master/javadocs/org/mozilla/jss/crypto/PKCS11Algorithm.html "org.mozilla.jss.crypto.PKCS11Algorithm" [jss-pkcs11-constants]: https://dogtagpki.github.io/jss/master/javadocs/org/mozilla/jss/pkcs11/PKCS11Constants.html "org.mozilla.jss.pkcs11.PKCS11Constants" [kbkdf-counter-params]: https://dogtagpki.github.io/jss/master/javadocs/org/mozilla/jss/crypto/KBKDFCounterParams.html "org.mozilla.jss.crypto.KBKDFCounterParams" [kbkdf-feedback-params]: https://dogtagpki.github.io/jss/master/javadocs/org/mozilla/jss/crypto/KBKDFFeedbackParams.html "org.mozilla.jss.crypto.KBKDFFeedbackParams" [kbkdf-pipeline-params]: https://dogtagpki.github.io/jss/master/javadocs/org/mozilla/jss/crypto/KBKDFPipelineParams.html "org.mozilla.jss.crypto.KBKDFPipelineParams" [kbkdf-spec]: https://dogtagpki.github.io/jss/master/javadocs/org/mozilla/jss/crypto/KBKDFParameterSpec.html "org.mozilla.jss.crypto.KBKDFParameterSpec" [kbkdf-spec-set-prf]: https://dogtagpki.github.io/jss/master/javadocs/org/mozilla/jss/crypto/KBKDFParameterSpec.html#setPRF-org.mozilla.jss.crypto.PKCS11Algorithm- "org.mozilla.jss.crypto.KBKDFParameterSpec setPRF(...)" [kbkdf-spec-set-prf-key]: https://dogtagpki.github.io/jss/master/javadocs/org/mozilla/jss/crypto/KBKDFParameterSpec.html#setPRFKey-javax.crypto.SecretKey- "org.mozilla.jss.crypto.KBKDFParameterSpec setPRFKey(...)" [kbkdf-spec-set-derived-algo]: https://dogtagpki.github.io/jss/master/javadocs/org/mozilla/jss/crypto/KBKDFParameterSpec.html#setDerivedKeyAlgorithm-org.mozilla.jss.crypto.PKCS11Algorithm- "org.mozilla.jss.crypto.KBKDFParameterSpec setDerivedKeyAlgorithm(...)" [kbkdf-spec-set-key-size]: https://dogtagpki.github.io/jss/master/javadocs/org/mozilla/jss/crypto/KBKDFParameterSpec.html#setKeySize-int- "org.mozilla.jss.crypto.KBKDFParameterSpec setKeySize(...)" [kbkdf-spec-set-iv]: https://dogtagpki.github.io/jss/master/javadocs/org/mozilla/jss/crypto/KBKDFFeedbackParams.html [kbkdf-spec-set-params]: https://dogtagpki.github.io/jss/master/javadocs/org/mozilla/jss/crypto/KBKDFParameterSpec.html#setParameters-org.mozilla.jss.crypto.KBKDFDataParameter:A- "org.mozilla.jss.crypto.KBKDFParameterSpec setParameters(...)" [kbkdf-spec-add-param]: https://dogtagpki.github.io/jss/master/javadocs/org/mozilla/jss/crypto/KBKDFParameterSpec.html#addParameter-org.mozilla.jss.crypto.KBKDFDataParameter- "org.mozilla.jss.crypto.KBKDFParameterSpec addParameter(...)" [kbkdf-spec-set-keys]: https://dogtagpki.github.io/jss/master/javadocs/org/mozilla/jss/crypto/KBKDFParameterSpec.html#setAdditionalDerivedKeys-org.mozilla.jss.crypto.KBKDFDerivedKey:A- "org.mozilla.jss.crypto.KBKDFParameterSpec setAdditionalDerivedKeys(...)" [kbkdf-spec-add-key]: https://dogtagpki.github.io/jss/master/javadocs/org/mozilla/jss/crypto/KBKDFParameterSpec.html#addAdditionalDerivedKey-org.mozilla.jss.crypto.KBKDFDerivedKey- "org.mozilla.jss.crypto.KBKDFParameterSpec addAdditionalDerivedKey(...)" [key-generator]: https://docs.oracle.com/javase/8/docs/api/javax/crypto/KeyGenerator.html "javax.crypto.KeyGenerator" [native-enclosure]: https://dogtagpki.github.io/jss/master/javadocs/org/mozilla/jss/util/NativeEnclosure.html "org.mozilla.jss.util.NativeEnclosure" [native-proxy]: https://dogtagpki.github.io/jss/master/javadocs/org/mozilla/jss/util/NativeProxy.html "org.mozilla.jss.util.NativeProxy" [pkcs11-kbkdf]: https://docs.oasis-open.org/pkcs11/pkcs11-curr/v3.0/csprd01/pkcs11-curr-v3.0-csprd01.html#_Toc437440585 "PKCS#11 v3.0: SP 800-108 Key Derivation" [pkcs11-kbkdf-params]: https://docs.oasis-open.org/pkcs11/pkcs11-curr/v3.0/csprd01/pkcs11-curr-v3.0-csprd01.html#_Toc8118473 "PKCS#11 v3.0: SP 800-108 Key Derivation: 2.42.2 Mechanism Parameters" [pkcs11-kbkdf-adk]: https://docs.oasis-open.org/pkcs11/pkcs11-curr/v3.0/csprd01/pkcs11-curr-v3.0-csprd01.html#_Toc8118477 "PKCS#11 v3.0: SP 800-108 Key Derivation: 2.42.6 Deriving Additional Keys" [sp800-108]: https://csrc.nist.gov/publications/detail/sp/800-108/final "Recommendation for Key Derivation using Pseudorandom Functions (Revised)" jss-5.0.0/docs/using_jss.md000066400000000000000000000030611412550063600155730ustar00rootroot00000000000000# Using JSS Please make sure `libjss.so` is included in your library path or set it via the `LD_LIBRARY_PATH` environment variable. See `man 8 ld.so` for more information. Alternatively, this can be done by setting `-Djava.library.path` to the directory with `libjss.so` on the command line of all Java programs using JSS. Note that without `libjss.so`, using JSS in nearly any capacity will fail. ## Classpath Dependencies To use JSS in your project after installation, you'll need to ensure the following dependencies are available in your `CLASSPATH`: - `jss.jar` -- provided by the `jss` package and installed to `/usr/lib/java/jss.jar`. - `slf4j-api.jar` -- provided by the `slf4j` package and installed to `/usr/share/java/slf4j/slf4j-api.jar`. - `apache-commons-lang.jar` -- provided by the `apache-commons-lang` package and installed to `/usr/share/java/apache-commons-lang.jar`. Note that the above paths and packages are for Fedora; for a list of packages in Debian, please see the [dependencies document](dependencies.md). Note that paths might differ between various platforms and versions of Fedora. ## Developing against JSS We recommend referring to the javadoc distribution generated when JSS was installed. On Fedora-like systems, this is provided by the `jss-javadoc` package; for an online version tracking master, please refer to our [live instance](https://dogtagpki.github.io/jss/javadoc/index.html). ## More Information For more information about using JSS, please see our documentation on loading the [`JSSProvider`](usage/jssprovider.md). jss-5.0.0/examples/000077500000000000000000000000001412550063600141335ustar00rootroot00000000000000jss-5.0.0/examples/README.adoc000066400000000000000000000004111412550063600157140ustar00rootroot00000000000000= JSS Examples = Below are examples of how to use JSS: * link:src/main/java/examples/pkcs12.java[pkcs12.java] * link:src/main/java/examples/PQGGen.java[PQGGen.java] More examples are available in the link:../src/test/java/org/mozilla/jss/tests[tests] directory. jss-5.0.0/examples/pom.xml000066400000000000000000000017761412550063600154630ustar00rootroot00000000000000 4.0.0 org.dogtagpki jss-example 5.0.0-SNAPSHOT org.dogtagpki jss 5.0.0-SNAPSHOT org.apache.maven.plugins maven-compiler-plugin 3.8.1 11 jss-5.0.0/examples/src/000077500000000000000000000000001412550063600147225ustar00rootroot00000000000000jss-5.0.0/examples/src/main/000077500000000000000000000000001412550063600156465ustar00rootroot00000000000000jss-5.0.0/examples/src/main/java/000077500000000000000000000000001412550063600165675ustar00rootroot00000000000000jss-5.0.0/examples/src/main/java/examples/000077500000000000000000000000001412550063600204055ustar00rootroot00000000000000jss-5.0.0/examples/src/main/java/examples/PQGGen.java000066400000000000000000000036351412550063600223400ustar00rootroot00000000000000package examples; /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import org.mozilla.jss.*; import org.mozilla.jss.crypto.*; /** * A command-line utility for generating PQG parameters for DSA * Key operations. Can be used for testing. * Takes the keysize as the sole argument. */ public class PQGGen { public static void main(String args[]) { int size; PQGParams pqg; try { if(args.length != 1) { throw new Exception("Usage: java PQGGen "); } size = Integer.parseInt(args[0]); System.out.println("Generating PQG parameters for "+size+ "-bit keypairs. This could take hours..."); CryptoManager.initialize("."); pqg = PQGParams.generate(size); System.out.println("Generated PQG Parameters."); System.out.println("Verifying PQG Parameters. "+ "This could take a few minutes..."); if( ! pqg.paramsAreValid() ) { throw new Exception("ERROR: Generated parameters are invalid."); } System.out.println("Parameters are valid!"); System.out.println("P: "+pqg.getP()); System.out.println("Q: "+pqg.getQ()); System.out.println("G: "+pqg.getG()); System.out.println("H: "+pqg.getH()); System.out.println("seed: "+pqg.getSeed()); System.out.println("counter: "+pqg.getCounter()); } catch(NumberFormatException e) { System.err.println("Invalid key size: "+e); } catch(PQGParamGenException e) { System.err.println(e); } catch(java.security.InvalidParameterException e) { System.err.println("Invalid key size: "+e); } catch(Exception e) { System.err.println(e); } } } jss-5.0.0/examples/src/main/java/examples/pkcs12.java000066400000000000000000000263251412550063600223630ustar00rootroot00000000000000package examples; /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** * This program reads in a PKCS #12 file and dumps its contents to the screen. * At the same time, it creates a new PKCS #12 file. As it reads through the * old file, it writes its contents into the new file. Then the new file * is encrypted and MACed with a new, different password. */ /* note that this code still has some problems reading PKCS12 file * generated with Communicator. */ import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BMPString; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.SET; import org.mozilla.jss.crypto.CryptoStore; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.JSSSecureRandom; import org.mozilla.jss.crypto.PBEAlgorithm; import org.mozilla.jss.crypto.PrivateKey; import org.mozilla.jss.pkcs12.AuthenticatedSafes; import org.mozilla.jss.pkcs12.CertBag; import org.mozilla.jss.pkcs12.PFX; import org.mozilla.jss.pkcs12.PasswordConverter; import org.mozilla.jss.pkcs12.SafeBag; import org.mozilla.jss.pkix.cert.Certificate; import org.mozilla.jss.pkix.primitive.Attribute; import org.mozilla.jss.pkix.primitive.EncryptedPrivateKeyInfo; import org.mozilla.jss.pkix.primitive.PrivateKeyInfo; import org.mozilla.jss.util.ConsolePasswordCallback; import org.mozilla.jss.util.Password; public class pkcs12 { public static void main(String []args) { try { // Read arguments if( args.length != 3 ) { System.out.println("Usage: PFX "); System.exit(-1); } // open input file for reading FileInputStream infile=null; try { infile = new FileInputStream(args[1]); } catch (FileNotFoundException f) { System.out.println("Cannot open file "+args[1]+ " for reading: "+f.getMessage()); return; } int certfile = 0; // initialize CryptoManager. This is necessary because there is // crypto involved with decoding a PKCS #12 file CryptoManager.initialize( args[0] ); CryptoManager manager = CryptoManager.getInstance(); // Decode the P12 file PFX.Template pfxt = new PFX.Template(); PFX pfx; try (BufferedInputStream is = new BufferedInputStream(infile, 2048)) { pfx = (PFX) pfxt.decode(is); } System.out.println("Decoded PFX"); // print out information about the top-level PFX structure System.out.println("Version: "+pfx.getVersion()); AuthenticatedSafes authSafes = pfx.getAuthSafes(); SEQUENCE safeContentsSequence = authSafes.getSequence(); System.out.println("AuthSafes has "+ safeContentsSequence.size()+" SafeContents"); // Get the password for the old file System.out.println("Enter password: "); Password pass = Password.readPasswordFromConsole(); // get new password, which will be used for the new file we create // later System.out.println("Enter new password:"); Password newPass = Password.readPasswordFromConsole(); // Verify the MAC on the PFX. This is important to be sure // it hasn't been tampered with. StringBuffer sb = new StringBuffer(); if( pfx.verifyAuthSafes(pass, sb) ) { System.out.println("AuthSafes verifies correctly."); } else { System.out.println("AuthSafes failed to verify because: "+ sb); } // Create a new AuthenticatedSafes. As we read the contents of the // old authSafes, we will store them into the new one. After we have // cycled through all the contents, they will all have been copied into // the new authSafes. AuthenticatedSafes newAuthSafes = new AuthenticatedSafes(); // Loop over contents of the old authenticated safes //for(int i=0; i < asSeq.size(); i++) { for(int i=0; i < safeContentsSequence.size(); i++) { // The safeContents may or may not be encrypted. We always send // the password in. It will get used if it is needed. If the // decryption of the safeContents fails for some reason (like // a bad password), then this method will throw an exception SEQUENCE safeContents = authSafes.getSafeContentsAt(pass, i); System.out.println("\n\nSafeContents #"+i+" has "+ safeContents.size()+" bags"); // Go through all the bags in this SafeContents for(int j=0; j < safeContents.size(); j++) { SafeBag safeBag = (SafeBag) safeContents.elementAt(j); // The type of the bag is an OID System.out.println("\nBag "+j+" has type "+ safeBag.getBagType() ); // look for bag attributes SET attribs = safeBag.getBagAttributes(); if( attribs == null ) { System.out.println("Bag has no attributes"); } else { for(int b=0; b < attribs.size(); b++) { Attribute a = (Attribute) attribs.elementAt(b); if( a.getType().equals(SafeBag.FRIENDLY_NAME)) { // the friendly name attribute is a nickname BMPString bs = (BMPString) ((ANY)a.getValues(). elementAt(0)).decodeWith( BMPString.getTemplate()); System.out.println("Friendly Name: "+bs); } else if(a.getType().equals(SafeBag.LOCAL_KEY_ID)){ // the local key id is used to match a key // to its cert. The key id is the SHA-1 hash of // the DER-encoded cert. OCTET_STRING os =(OCTET_STRING) ((ANY)a.getValues(). elementAt(0)).decodeWith( OCTET_STRING.getTemplate()); System.out.println("LocalKeyID:"); /* AuthenticatedSafes. print_byte_array(os.toByteArray()); */ } else { System.out.println("Unknown attribute type: "+ a.getType().toString()); } } } // now look at the contents of the bag ASN1Value val = safeBag.getInterpretedBagContent(); if( val instanceof PrivateKeyInfo ) { // A PrivateKeyInfo contains an unencrypted private key System.out.println("content is PrivateKeyInfo"); } else if( val instanceof EncryptedPrivateKeyInfo ) { // An EncryptedPrivateKeyInfo is, well, an encrypted // PrivateKeyInfo. Usually, strong crypto is used in // an EncryptedPrivateKeyInfo. EncryptedPrivateKeyInfo epki = ((EncryptedPrivateKeyInfo)val); System.out.println( "content is EncryptedPrivateKeyInfo, algoid:" + epki.getEncryptionAlgorithm().getOID()); // Because we are in a PKCS #12 file, the passwords are // char-to-byte converted in a special way. We have to // use the special converter class instead of the default. PrivateKeyInfo pki = epki.decrypt(pass, new org.mozilla.jss.pkcs12.PasswordConverter() ); // import the key into the key3.db CryptoToken tok = manager.getTokenByName("Internal Key Storage Token"); CryptoStore store = tok.getCryptoStore(); tok.login( new ConsolePasswordCallback()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); pki.encode(baos); store.importPrivateKey(baos.toByteArray(), PrivateKey.RSA); // re-encrypt the PrivateKeyInfo with the new password // and random salt byte[] salt = new byte[ PBEAlgorithm.PBE_SHA1_DES3_CBC.getSaltLength()]; JSSSecureRandom rand = CryptoManager.getInstance(). getSecureRNG(); rand.nextBytes(salt); epki = EncryptedPrivateKeyInfo.createPBE( PBEAlgorithm.PBE_SHA1_DES3_CBC, newPass, salt, 1, new PasswordConverter(), pki); // Overwrite the previous EncryptedPrivateKeyInfo with // this new one we just created using the new password. // This is what will get put in the new PKCS #12 file // we are creating. safeContents.insertElementAt( new SafeBag( safeBag.getBagType(), epki, safeBag.getBagAttributes()), i); safeContents.removeElementAt(i+1); } else if( val instanceof CertBag ) { System.out.println("content is CertBag"); CertBag cb = (CertBag) val; if( cb.getCertType().equals(CertBag.X509_CERT_TYPE)) { // this is an X.509 certificate OCTET_STRING os = (OCTET_STRING)cb.getInterpretedCert(); Certificate cert = (Certificate) ASN1Util.decode(Certificate.getTemplate(), os.toByteArray()); cert.getInfo().print(System.out); } else { System.out.println("Unrecognized cert type"); } } else { System.out.println("content is ANY"); } } // Add the new safe contents to the new authsafes if( authSafes.safeContentsIsEncrypted(i) ) { newAuthSafes.addEncryptedSafeContents( AuthenticatedSafes.DEFAULT_KEY_GEN_ALG, newPass, null, AuthenticatedSafes.DEFAULT_ITERATIONS, safeContents); } else { newAuthSafes.addSafeContents( safeContents ); } } // Create new PFX from the new authsafes PFX newPfx = new PFX(newAuthSafes); // Add a MAC to the new PFX newPfx.computeMacData(newPass, null, PFX.DEFAULT_ITERATIONS); // write the new PFX out to a file FileOutputStream fos = new FileOutputStream(args[2]); newPfx.encode(fos); fos.close(); } catch( Exception e ) { e.printStackTrace(); } } } jss-5.0.0/examples/src/main/resources/000077500000000000000000000000001412550063600176605ustar00rootroot00000000000000jss-5.0.0/examples/src/main/resources/inputfile.pfx000066400000000000000000000103221412550063600223740ustar00rootroot000000000000000€0€ *†H†÷  €$€0€0€  *†H†÷  €$€0‚0‚   *†H†÷   ‚¥0‚¡0   *†H†÷  0 Ð*vÃ~Å/[‚€‚€‚€–Å=õC,ʆ´éƒLÖKQ÷ˆt¹ôrÒ„ó#QA¼R×–Ø×É3)c‡gˆqÃȵÝG?o;féÙ€H ø[yûspXêmà%R–@4~Š€üQØ%:SÔΠ­ ‹}V¹úΛ Eš=Êól¥o+á÷K>;¯ 6¬m´#„aE±h5e?­/£:'ñ(¶y[8ô€ëfI (4Fq HãòG>5çÄÀí¿Ù‹t©c£%5­TLR[¹áÿÊÄÓl}lõ¨Öz–t›Ã¥¡Aü@ü¿ÀûÊ :›{“cè},Á»VBã®NØ25ëX àÚt16dÁÃÉ¥´CXcͽÓ[ƶ«4oûD?תz ¸OÉäUºüî´3ãqü½JʘZ—ƒ›fËF2ÜÙÊ>|ûR„½’µßŠÀ¦Î¯†ïÖV ˜ž-Â!Mna–vàK·%s.\# ¨t‘Q@/™¤•zˆ´ê›BñâMáàÅÖ1®¢WÜq I:£Ä;÷©!¸ö–Ö~0; ôTZ7._ö%p¾¢Öß&Oî—½!ËÔfçѦ5v“¸¿Uµïu[Ÿ(ªWµÝiseçS"ýÞóN÷Œû…!#Nðˆ×)Œ.s•éQ`ïË ®‡íkG¯Þ,âð6ƒœ£ƒ[‹k7Wæƒ(Î £á;Qû/¾uÄz%,ÈÀ鸚༠?¿äU 5TÄÆÙü0 bÃ;JÔ™B1xN»+'±oÈ3Ç” !Ù«ûêñ`ö)MËGÑï÷MË<ý8qçaáÙ0Å.*%úªä¯ÐN¸ &Ì[K¹O1b0;   *†H†÷  1.,,,CMS Administrator's ID0#   *†H†÷  1ôé"HÍn!Ù+„¸_Ϋ0€  *†H†÷  €0€0€  *†H†÷ 0  *†H†÷  0 ˆ—Õù¶$ª €¾)ØÕ¸’Ì>ŒØoäqƇ8.¢Ð4Ebp a±ÀèípÁe€yz¥Á;ùmh‚‚¸‚¸òý*³Å/6GÚ[ÎÖ½@Ô» €ÛCBéߨè©òpvr3¡¡êr’«SÖ¾{KDÇK0ƒrþ2òYÑ®¥=“Wbשd¼gÚ®ÚŸêšRJŸ¢ñçbõYžïÎòò€c['y^t“ù쟴Wê„ó?ÔçmTt> ‰[ùSoÇʹ[©„;ø%à"„Ç ÞU=æ…6ÞëÍS-x¶` ~ÐP­£TÁpW<£âtœ„DÒõÿwj˜r&¤lV(c¾i7ŠÅ‹ál¬N@$}:¢›<ù·C¬aª¶ùÒfî;[Ó‘ÙÔ  Áñ±ßnVýì-•-‚„0x>kÚ…X7ž³’#{ªÜŒ¨%f,èâÁ ¤áwÛæqü-F“¶¤]Ù`Ìv-Ô23,,ÅÍB¶ší¹CÄ…㯿+I=2m`9 ð2]4ÿP*²½MPN=$ÃÄ1N0 UÐÑjá¤WòðU^Õþ0‹ð–¡þ«B§ð ¶^WYìû­VÉÕ…`+sEê4pï*`Å‹HGEãƒ)Ô©Üåç½:¤]?Ä™`S;ÚV‘ceαVi—S[²ºµéMßÇ4׈UÀ‚"Ô+‚æ]Þ/á ¢kvdµ[$µX½Lò8òö„‰œˆdÿeÁÜ‚Ä%Vo4óq'C0ß.ú'º¶íM6•¬¿ÌŒJml;$Üh‰KBÐíLM)¦Õ[wãÈl~ê` ý¶ŸmAý.RiŽkÓž‰ …8‰VS#îðjæUaÂÝÁŠcˆbH—›ãÝî\г‰?L éï.’'g™ýÓ š²ß5àv_Øi—|úWØcWc‡ë á^CŸ= àõ’ ûe–êwŒ™K›IÌ+ÙN~šL\EÌS˜î­Ṵ̀ÐT,ª"d4¼òȦζ QXÎÈÚ{’nrÔìÀÚw$ª`½“¬Òjhl¼”à¨á3OþeŠ·Â3¥‹Ùÿ1ŽÉÖyNÝ nY@$¶ÐJ}Å`‰C Ö³+_S­£î+ì p[o: «ô—͆n7Gq6Ñ@<îC!‰l¦‡R“Ò3 }ƒ£rK [[9½;c‘¶^µi&ó>zœ~m1!!¢Ì…ÜóŒ]è²ß3»¯'®fnAQ:6å>Y6ä0xà ñ’v8‹>܈GFª”Äþ|Ž©ˆ1ž5^»Â ü™d3¯ ‚£ÅOMtÝv͹„0ÌýKÕnö^(#Jr©˸n®¡Ÿðáè[&`äî+Éfi‡Ì°g9eº-«e ³›t"´~A3`=e)õ ¸ßq–PžÏ _{’ùîÀ\]èú˜3!Y7EíQV%i”,.‡Á¼‚ùªgÓe8dœSí XE*Lï˜á³„_cIIÚŠ_îŒfŠÁ°OËfl•æÀy¶qùµ#W6:0Æz °i0´üAšÿy¨¾.Y&6f/-®aU`?‹^Ž`D’PãÚ£ýRb’ OËÉâ˜!Û{pνÎ^LdcPO#eÃSaŠÄÚ~s7ê©Ñ‡„á‘4œÆÓ—'Ôrº4Ù\1r»ÖÌZhþ»è¿#g)ÿ†$Züýæ*.}õ×R£G*Š#¤Ž÷‚ÔŠCs–³2$kZ)~›à„¤\Ò ‡¦]3>@ZûaAL!öjŒØ{T/ûv Óè³K šT·äÈjûé…k±í×Eyµ ›ê·Å¥èxý}`'nç Äh9AŠ$ê'X&¢ðòxøÑ½„d쳟HÒ¯Fù. œruŸ¢Ñ¸Ž S ¨ÚoûÞ¸ñ<¤84k[P“ Œõdø™Åëm…—¯nb050!0 +ÁÒšžšÀ>c“TŸA~‘­µÅ¾‚¥n—zâ”p˜ îzÙá¯.jss-5.0.0/gpl.txt000066400000000000000000000431031412550063600136410ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. jss-5.0.0/jss.html000066400000000000000000000060261412550063600140060ustar00rootroot00000000000000 Netscape Security Services for Java

Netscape Security Services for Java

Netscape Security Services for Java (JSS) is an interface allowing Java applications to use the Secure Sockets Layer protocol. The interface is implemented with the FIPS-validated Netscape Security Services library. It consists of a system-dependent dynamic library (libjss.so on UNIX, jss.dll on Windows) and a ZIP file (jss.zip) containing system-independent Java classes. These classes are compatible with JDK 1.1 or later using the native thread implementation (not green threads).

Building Applications with JSS

To construct Java applications that use JSS, you must:
  • Call the JSS classes from your application.
  • When compiling your application, put jss.zip in your CLASSPATH.
  • When running your application, put libjss.so in your LD_LIBRARY_PATH (on UNIX) or jss.dll in your PATH (on Windows), and put jss.zip in your CLASSPATH.

Programming with JSS

Before the SSL classes can be used, NSSInit.initialize must be called to open the security databases and initialize the random number generator. NSSInit.setPasswordCallback may be called to change the password callback; the default is to prompt for passwords on the command line.

The files in the examples directory illustrate the use of JSS in an application:

SSLClient.java
An example of an SSL client application.
SSLServer.java
An example of an SSL server application. To run, it requires certificate and key databases that contain a certificate called "SSLServer". The sample cert7.db and key3.db files, also in the examples directory, can be used for this purpose. When SSLServer is run, it will ask for a password for the "Internal Key Storage Token", which is the key database. The password for the example key3.db file is "netscape".
These classes are in the org.mozilla.jss.ssl package. The .class files must be put in the subdirectory org/mozilla/jss/ssl of a CLASSPATH entry in order to be located by the Java virtual machine.

Javadoc for the JSS Classes

jss-5.0.0/jss.spec000066400000000000000000000115341412550063600137740ustar00rootroot00000000000000################################################################################ Name: jss ################################################################################ Summary: Java Security Services (JSS) URL: http://www.dogtagpki.org/wiki/JSS License: MPLv1.1 or GPLv2+ or LGPLv2+ # For development (i.e. unsupported) releases, use x.y.z-0.n.. # For official (i.e. supported) releases, use x.y.z-r where r >=1. Version: 5.0.0 Release: 1%{?_timestamp}%{?_commit_id}%{?dist} #global _phase -alpha1 # To generate the source tarball: # $ git clone https://github.com/dogtagpki/jss.git # $ cd jss # $ git tag v4.5. # $ git push origin v4.5. # Then go to https://github.com/dogtagpki/jss/releases and download the source # tarball. Source: https://github.com/dogtagpki/%{name}/archive/v%{version}%{?_phase}/%{name}-%{version}%{?_phase}.tar.gz # To create a patch for all changes since a version tag: # $ git format-patch \ # --stdout \ # \ # > jss-VERSION-RELEASE.patch # Patch: jss-VERSION-RELEASE.patch ################################################################################ # Java ################################################################################ %define java_devel java-11-openjdk-devel %define java_headless java-11-openjdk-headless %define java_home /usr/lib/jvm/jre-11-openjdk ################################################################################ # Build Options ################################################################################ # By default the javadoc package will be built unless --without javadoc # option is specified. %bcond_without javadoc # By default the build will execute unit tests unless --without test # option is specified. %bcond_without test ################################################################################ # Build Dependencies ################################################################################ BuildRequires: make BuildRequires: cmake >= 3.14 BuildRequires: zip BuildRequires: unzip BuildRequires: gcc-c++ BuildRequires: nss-devel >= 3.66 BuildRequires: nss-tools >= 3.66 BuildRequires: %{java_devel} BuildRequires: jpackage-utils BuildRequires: slf4j BuildRequires: slf4j-jdk14 BuildRequires: apache-commons-lang3 BuildRequires: junit Requires: nss >= 3.66 Requires: %{java_headless} Requires: jpackage-utils Requires: slf4j Requires: slf4j-jdk14 Requires: apache-commons-lang3 Conflicts: ldapjdk < 4.20 Conflicts: idm-console-framework < 1.2 Conflicts: tomcatjss < 7.6.0 Conflicts: pki-base < 10.10.0 %description Java Security Services (JSS) is a java native interface which provides a bridge for java-based applications to use native Network Security Services (NSS). This only works with gcj. Other JREs require that JCE providers be signed. %if %{with javadoc} ################################################################################ %package javadoc ################################################################################ Summary: Java Security Services (JSS) Javadocs Requires: jss = %{version}-%{release} %description javadoc This package contains the API documentation for JSS. %endif ################################################################################ %prep %autosetup -n %{name}-%{version}%{?_phase} -p 1 ################################################################################ %build %set_build_flags export JAVA_HOME=%{java_home} # Enable compiler optimizations export BUILD_OPT=1 # Generate symbolic info for debuggers CFLAGS="-g $RPM_OPT_FLAGS" export CFLAGS # Check if we're in FIPS mode modutil -dbdir /etc/pki/nssdb -chkfips true | grep -q enabled && export FIPS_ENABLED=1 ./build.sh \ %{?_verbose:-v} \ --work-dir=%{_vpath_builddir} \ --java-lib-dir=%{_jnidir} \ --jss-lib-dir=%{_libdir}/jss \ --version=%{version} \ %{!?with_javadoc:--without-javadoc} \ %{!?with_test:--without-test} \ dist ################################################################################ %install ./build.sh \ %{?_verbose:-v} \ --work-dir=%{_vpath_builddir} \ --install-dir=%{buildroot} \ install ################################################################################ %files %defattr(-,root,root,-) %doc jss.html %license MPL-1.1.txt gpl.txt lgpl.txt %{_libdir}/* %{_jnidir}/* %if %{with javadoc} ################################################################################ %files javadoc %defattr(-,root,root,-) %{_javadocdir}/%{name}/ %endif ################################################################################ %changelog * Tue May 29 2018 Dogtag PKI Team 4.5.0-0 - To list changes in since : $ git log --pretty=oneline --abbrev-commit --no-decorate .. jss-5.0.0/lgpl.txt000066400000000000000000000635041412550063600140240ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! jss-5.0.0/lib/000077500000000000000000000000001412550063600130635ustar00rootroot00000000000000jss-5.0.0/lib/MANIFEST.MF.in000066400000000000000000000005041412550063600151210ustar00rootroot00000000000000Manifest-Version: 1.0 Name: org/mozilla/jss/ Specification-Title: Network Security Services for Java (JSS) Specification-Version: ${JSS_VERSION_MANIFEST} Specification-Vendor: Mozilla Foundation Implementation-Title: org.mozilla.jss Implementation-Version: ${JSS_VERSION_MANIFEST} Implementation-Vendor: Mozilla Foundation jss-5.0.0/lib/java.security.Provider.in000066400000000000000000000000341412550063600177700ustar00rootroot00000000000000org.mozilla.jss.JSSProvider jss-5.0.0/lib/jss.map000066400000000000000000000550241412550063600143670ustar00rootroot00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # OK, this file is meant to support Linux's Version Script. For more # information, see: # ftp://ftp.gnu.org/pub/old-gnu/Manuals/ld-2.9.1/html_node/ld_25.html JSS_3.0 { # JSS 3.0 release global: Java_org_mozilla_jss_crypto_EncryptionAlgorithm_getIVLength; Java_org_mozilla_jss_crypto_PQGParams_generateNative__I; Java_org_mozilla_jss_crypto_PQGParams_generateNative__II; Java_org_mozilla_jss_crypto_PQGParams_paramsAreValidNative; Java_org_mozilla_jss_DatabaseCloser_closeDatabases; Java_org_mozilla_jss_CryptoManager_FIPSEnabled; Java_org_mozilla_jss_CryptoManager_buildCertificateChainNative; Java_org_mozilla_jss_CryptoManager_enableFIPS; Java_org_mozilla_jss_CryptoManager_exportCertsToPKCS7; Java_org_mozilla_jss_CryptoManager_findCertByIssuerAndSerialNumberNative; Java_org_mozilla_jss_CryptoManager_findCertByNicknameNative; Java_org_mozilla_jss_CryptoManager_findCertsByNicknameNative; Java_org_mozilla_jss_CryptoManager_findPrivKeyByCertNative; Java_org_mozilla_jss_CryptoManager_getCACerts; Java_org_mozilla_jss_CryptoManager_getPermCerts; Java_org_mozilla_jss_CryptoManager_importCRLNative; Java_org_mozilla_jss_CryptoManager_importCertPackageNative; Java_org_mozilla_jss_CryptoManager_importCertToPermNative; Java_org_mozilla_jss_CryptoManager_initializeAllNative; Java_org_mozilla_jss_CryptoManager_putModulesInVector; Java_org_mozilla_jss_CryptoManager_setNativePasswordCallback; Java_org_mozilla_jss_pkcs11_CertProxy_releaseNativeResources; Java_org_mozilla_jss_pkcs11_CipherContextProxy_releaseNativeResources; Java_org_mozilla_jss_pkcs11_PK11Module_getLibraryName; Java_org_mozilla_jss_pkcs11_PK11Module_getName; Java_org_mozilla_jss_pkcs11_PK11Module_putTokensInVector; Java_org_mozilla_jss_pkcs11_ModuleProxy_releaseNativeResources; Java_org_mozilla_jss_pkcs11_PK11Cert_getEncoded; Java_org_mozilla_jss_pkcs11_PK11Cert_getIssuerDNString; Java_org_mozilla_jss_pkcs11_PK11Cert_getNickname; Java_org_mozilla_jss_pkcs11_PK11Cert_getOwningToken; Java_org_mozilla_jss_pkcs11_PK11Cert_getPublicKey; Java_org_mozilla_jss_pkcs11_PK11Cert_getSerialNumberByteArray; Java_org_mozilla_jss_pkcs11_PK11Cert_getSubjectDNString; Java_org_mozilla_jss_pkcs11_PK11Cert_getTrust; Java_org_mozilla_jss_pkcs11_PK11Cert_getUniqueID; Java_org_mozilla_jss_pkcs11_PK11Cert_getVersion; Java_org_mozilla_jss_pkcs11_PK11Cert_setTrust; Java_org_mozilla_jss_pkcs11_PK11Cipher_finalizeContext; Java_org_mozilla_jss_pkcs11_PK11Cipher_initContext; Java_org_mozilla_jss_pkcs11_PK11Cipher_updateContext; Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeUnwrapPrivWithSym; Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeUnwrapSymWithPriv; Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeUnwrapSymWithSym; Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeWrapPrivWithSym; Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeWrapSymWithPub; Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeWrapSymWithSym; Java_org_mozilla_jss_pkcs11_PK11MessageDigest_digest; Java_org_mozilla_jss_pkcs11_PK11MessageDigest_initDigest; Java_org_mozilla_jss_pkcs11_PK11MessageDigest_initHMAC; Java_org_mozilla_jss_pkcs11_PK11MessageDigest_update; Java_org_mozilla_jss_pkcs11_PK11PrivKey_getKeyType; Java_org_mozilla_jss_pkcs11_PK11PrivKey_getOwningToken; Java_org_mozilla_jss_pkcs11_PK11PrivKey_getStrength; Java_org_mozilla_jss_pkcs11_PK11PrivKey_getUniqueID; Java_org_mozilla_jss_pkcs11_PK11PrivKey_verifyKeyIsOnToken; Java_org_mozilla_jss_pkcs11_PK11PubKey_DSAFromRaw; Java_org_mozilla_jss_pkcs11_PK11PubKey_RSAFromRaw; Java_org_mozilla_jss_pkcs11_PK11PubKey_getEncoded; Java_org_mozilla_jss_pkcs11_PK11PubKey_getKeyType; Java_org_mozilla_jss_pkcs11_PK11PubKey_verifyKeyIsOnToken; Java_org_mozilla_jss_pkcs11_PK11SymKey_getKeyData; Java_org_mozilla_jss_pkcs11_PK11SymKey_getKeyType; Java_org_mozilla_jss_pkcs11_PK11SymKey_getOwningToken; Java_org_mozilla_jss_pkcs11_PK11SymKey_getStrength; Java_org_mozilla_jss_pkcs11_PK11KeyPairGenerator_generateDSAKeyPair; Java_org_mozilla_jss_pkcs11_PK11KeyPairGenerator_generateRSAKeyPair; Java_org_mozilla_jss_pkcs11_PK11KeyGenerator_generateNormal; Java_org_mozilla_jss_pkcs11_PK11KeyGenerator_generatePBE; Java_org_mozilla_jss_pkcs11_PK11KeyGenerator_generatePBE_1IV; Java_org_mozilla_jss_pkcs11_PK11KeyGenerator_nativeClone; Java_org_mozilla_jss_pkcs11_PrivateKeyProxy_releaseNativeResources; Java_org_mozilla_jss_pkcs11_PublicKeyProxy_releaseNativeResources; Java_org_mozilla_jss_pkcs11_SymKeyProxy_releaseNativeResources; Java_org_mozilla_jss_pkcs11_PK11Token_PWInitable; Java_org_mozilla_jss_pkcs11_PK11Token_SSOPasswordIsCorrect; Java_org_mozilla_jss_pkcs11_PK11Token_changePassword; Java_org_mozilla_jss_pkcs11_PK11Token_doesAlgorithm; Java_org_mozilla_jss_pkcs11_PK11Token_generatePK10; Java_org_mozilla_jss_pkcs11_PK11Token_getLoginMode; Java_org_mozilla_jss_pkcs11_PK11Token_getLoginTimeoutMinutes; Java_org_mozilla_jss_pkcs11_PK11Token_getName; Java_org_mozilla_jss_pkcs11_PK11Token_initPassword; Java_org_mozilla_jss_pkcs11_PK11Token_isLoggedIn; Java_org_mozilla_jss_pkcs11_PK11Token_isPresent; Java_org_mozilla_jss_pkcs11_PK11Token_isWritable; Java_org_mozilla_jss_pkcs11_PK11Token_logout; Java_org_mozilla_jss_pkcs11_PK11Token_nativeLogin; Java_org_mozilla_jss_pkcs11_PK11Token_passwordIsInitialized; Java_org_mozilla_jss_pkcs11_PK11Token_setLoginMode; Java_org_mozilla_jss_pkcs11_PK11Token_setLoginTimeoutMinutes; Java_org_mozilla_jss_pkcs11_PK11Token_userPasswordIsCorrect; Java_org_mozilla_jss_pkcs11_TokenProxy_releaseNativeResources; Java_org_mozilla_jss_pkcs11_PK11Signature_engineRawSignNative; Java_org_mozilla_jss_pkcs11_PK11Signature_engineRawVerifyNative; Java_org_mozilla_jss_pkcs11_PK11Signature_engineSignNative; Java_org_mozilla_jss_pkcs11_PK11Signature_engineUpdateNative; Java_org_mozilla_jss_pkcs11_PK11Signature_engineVerifyNative; Java_org_mozilla_jss_pkcs11_PK11Signature_initSigContext; Java_org_mozilla_jss_pkcs11_PK11Signature_initVfyContext; Java_org_mozilla_jss_pkcs11_PK11Store_deleteCert; Java_org_mozilla_jss_pkcs11_PK11Store_deletePrivateKey; Java_org_mozilla_jss_pkcs11_PK11Store_importPrivateKey; Java_org_mozilla_jss_pkcs11_PK11Store_putCertsInVector; Java_org_mozilla_jss_pkcs11_PK11Store_putKeysInVector; Java_org_mozilla_jss_pkcs11_PK11Store_putSymKeysInVector; Java_org_mozilla_jss_pkcs11_PK11Store_putSymKeysInVector; Java_org_mozilla_jss_pkcs11_SigContextProxy_releaseNativeResources; Java_org_mozilla_jss_pkcs11_PK11RSAPublicKey_getModulusByteArray; Java_org_mozilla_jss_pkcs11_PK11RSAPublicKey_getPublicExponentByteArray; Java_org_mozilla_jss_pkcs11_PK11DSAPublicKey_getGByteArray; Java_org_mozilla_jss_pkcs11_PK11DSAPublicKey_getPByteArray; Java_org_mozilla_jss_pkcs11_PK11DSAPublicKey_getQByteArray; Java_org_mozilla_jss_pkcs11_PK11DSAPublicKey_getYByteArray; Java_org_mozilla_jss_pkcs11_PK11SecureRandom_nextBytes; Java_org_mozilla_jss_pkcs11_PK11SecureRandom_setSeed; Java_org_mozilla_jss_ssl_SSLServerSocket_clearSessionCache; Java_org_mozilla_jss_ssl_SSLServerSocket_configServerSessionIDCache; Java_org_mozilla_jss_ssl_SSLServerSocket_setServerCertNickname; Java_org_mozilla_jss_ssl_SSLServerSocket_socketAccept; Java_org_mozilla_jss_ssl_SSLServerSocket_socketListen; Java_org_mozilla_jss_ssl_SSLSocket_forceHandshake; Java_org_mozilla_jss_ssl_SSLSocket_getKeepAlive; Java_org_mozilla_jss_ssl_SSLSocket_getLocalAddressNative; Java_org_mozilla_jss_ssl_SocketBase_getLocalAddressByteArrayNative; Java_org_mozilla_jss_ssl_SSLSocket_getPort; Java_org_mozilla_jss_ssl_SSLSocket_getReceiveBufferSize; Java_org_mozilla_jss_ssl_SSLSocket_getSendBufferSize; Java_org_mozilla_jss_ssl_SSLSocket_getSoLinger; Java_org_mozilla_jss_ssl_SSLSocket_getStatus; Java_org_mozilla_jss_ssl_SSLSocket_getTcpNoDelay; Java_org_mozilla_jss_ssl_SSLSocket_invalidateSession; Java_org_mozilla_jss_ssl_SSLSocket_redoHandshake; Java_org_mozilla_jss_ssl_SSLSocket_resetHandshakeNative; Java_org_mozilla_jss_ssl_SSLSocket_setCipherPolicyNative; Java_org_mozilla_jss_ssl_SSLSocket_setCipherPreference; Java_org_mozilla_jss_ssl_SSLSocket_setKeepAlive; Java_org_mozilla_jss_ssl_SSLSocket_setReceiveBufferSize; Java_org_mozilla_jss_ssl_SSLSocket_setSSLDefaultOption; Java_org_mozilla_jss_ssl_SSLSocket_setSendBufferSize; Java_org_mozilla_jss_ssl_SSLSocket_setSoLinger; Java_org_mozilla_jss_ssl_SSLSocket_setTcpNoDelay; Java_org_mozilla_jss_ssl_SSLSocket_shutdownNative; Java_org_mozilla_jss_ssl_SSLSocket_socketAvailable; Java_org_mozilla_jss_ssl_SSLSocket_socketConnect; Java_org_mozilla_jss_ssl_SSLSocket_socketRead; Java_org_mozilla_jss_ssl_SSLSocket_socketWrite; Java_org_mozilla_jss_ssl_SocketBase_getLocalPortNative; Java_org_mozilla_jss_ssl_SocketBase_getPeerAddressNative; Java_org_mozilla_jss_ssl_SocketBase_getPeerAddressByteArrayNative; Java_org_mozilla_jss_ssl_SocketBase_setClientCertNicknameNative; Java_org_mozilla_jss_ssl_SocketBase_requestClientAuthNoExpiryCheckNative; Java_org_mozilla_jss_ssl_SocketBase_setSSLOption; Java_org_mozilla_jss_ssl_SocketBase_socketBind; Java_org_mozilla_jss_ssl_SocketBase_socketClose; Java_org_mozilla_jss_ssl_SocketBase_socketCreate; Java_org_mozilla_jss_util_Password_readPasswordFromConsole; # # Data objects (NONE) # # # commands (NONE) # # local: *; }; JSS_3.1 { # JSS 3.1 release global: Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeUnwrapSymPlaintext; Java_org_mozilla_jss_pkcs11_PK11Store_getEncryptedPrivateKeyInfo; local: *; }; JSS_3.1.1 { # JSS 3.1.1 release global: Java_org_mozilla_jss_ssl_SSLServerSocket_setReuseAddress; Java_org_mozilla_jss_ssl_SSLServerSocket_getReuseAddress; local: *; }; JSS_3.2 { # JSS 3.2 release global: Java_org_mozilla_jss_crypto_SecretDecoderRing_encrypt; Java_org_mozilla_jss_crypto_SecretDecoderRing_decrypt; Java_org_mozilla_jss_pkcs11_PK11PrivKey_fromPrivateKeyInfo; Java_org_mozilla_jss_pkcs11_PK11PubKey_fromRawNative; Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_getRawAliases; Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_engineDeleteEntry; Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_getDERCert; Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_getCertNickname; Java_org_mozilla_jss_pkcs11_PK11PubKey_fromSPKI; Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_engineGetKey; Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_engineIsCertificateEntry; Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_engineSetKeyEntryNative; Java_org_mozilla_jss_CryptoManager_initializeAllNative2; Java_org_mozilla_jss_ssl_SocketBase_getLocalAddressNative; Java_org_mozilla_jss_pkcs11_PK11PrivKey_getDSAParamsNative; Java_org_mozilla_jss_CryptoManager_verifyCertNowNative; Java_org_mozilla_jss_ssl_SSLServerSocket_setServerCert; Java_org_mozilla_jss_ssl_SocketBase_setClientCert; Java_org_mozilla_jss_CryptoManager_verifyCertTempNative; Java_org_mozilla_jss_ssl_SocketProxy_releaseNativeResources; local: *; }; JSS_3.3 { # JSS 3.3 release global: Java_org_mozilla_jss_ssl_SSLSocket_getImplementedCipherSuites; Java_org_mozilla_jss_ssl_SSLSocket_getCipherPreferenceDefault; Java_org_mozilla_jss_ssl_SSLSocket_setCipherPreferenceDefault; Java_org_mozilla_jss_ssl_SSLSocket_getCipherPreference; Java_org_mozilla_jss_CryptoManager_configureOCSPNative; Java_org_mozilla_jss_pkcs11_PK11SymKey_getLength; Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_getCertObject; Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_engineGetKeyNative; Java_org_mozilla_jss_SecretDecoderRing_KeyManager_generateKeyNative; Java_org_mozilla_jss_SecretDecoderRing_KeyManager_lookupKeyNative; Java_org_mozilla_jss_SecretDecoderRing_KeyManager_deleteKeyNative; local: *; }; JSS_3.4 { # JSS 3.4 release global: Java_org_mozilla_jss_pkcs11_PK11Cipher_initContextWithKeyBits; local: *; }; JSS_3.5 { # JSS 3.5 release global: Java_org_mozilla_jss_SecretDecoderRing_KeyManager_generateUniqueNamedKeyNative; Java_org_mozilla_jss_SecretDecoderRing_KeyManager_lookupUniqueNamedKeyNative; local: *; }; JSS_4.1 { # JSS 4.1 release global: Java_org_mozilla_jss_ssl_SSLSocket_abortReadWrite; Java_org_mozilla_jss_ssl_SSLServerSocket_abortAccept; local: *; }; JSS_4.2 { # JSS 4.2 release global: Java_org_mozilla_jss_ssl_SocketBase_getSSLOption; Java_org_mozilla_jss_ssl_SSLSocket_getSSLDefaultOption; Java_org_mozilla_jss_pkcs11_PK11Store_deleteCertOnly; local: *; }; JSS_4.2.3 { # JSS 4.2.3 release global: Java_org_mozilla_jss_pkcs11_PK11ECPublicKey_getCurveByteArray; Java_org_mozilla_jss_pkcs11_PK11ECPublicKey_getWByteArray; Java_org_mozilla_jss_pkcs11_PK11KeyPairGenerator_generateECKeyPair; local: *; }; JSS_4.2.5 { # JSS 4.2.5 release global: Java_org_mozilla_jss_ssl_SSLSocket_setSSLDefaultOptionMode; Java_org_mozilla_jss_ssl_SocketBase_setSSLOptionMode; Java_org_mozilla_jss_ssl_SSLSocket_isFipsCipherSuiteNative; local: *; }; JSS_4.3 { # JSS 4.3 release global: Java_org_mozilla_jss_pkcs11_PK11Token_needsLogin; local: *; }; JSS_4.2.6 { # JSS 4.2.6 release global: Java_org_mozilla_jss_pkcs11_PK11KeyPairGenerator_generateECKeyPairWithOpFlags; Java_org_mozilla_jss_pkcs11_PK11KeyPairGenerator_generateRSAKeyPairWithOpFlags; Java_org_mozilla_jss_pkcs11_PK11KeyPairGenerator_generateDSAKeyPairWithOpFlags; Java_org_mozilla_jss_CryptoManager_OCSPCacheSettingsNative; Java_org_mozilla_jss_CryptoManager_setOCSPTimeoutNative; Java_org_mozilla_jss_CryptoManager_verifyCertificateNowNative; Java_org_mozilla_jss_CryptoManager_verifyCertificateNowNative2; Java_org_mozilla_jss_CryptoManager_verifyCertificateNowCUNative; Java_org_mozilla_jss_asn1_ASN1Util_getTagDescriptionByOid; Java_org_mozilla_jss_ssl_SocketBase_setSSLVersionRange; Java_org_mozilla_jss_ssl_SSLSocket_setSSLVersionRangeDefault; Java_org_mozilla_jss_pkcs11_PK11SymmetricKeyDeriver_nativeDeriveSymKey; Java_org_mozilla_jss_pkcs11_PK11SymKey_setNickNameNative; local: *; }; JSS_4.3.1 { # JSS 4.3.1 release global: Java_org_mozilla_jss_pkcs11_PK11KeyPairGenerator_generateECKeyPairWithOpFlags; Java_org_mozilla_jss_pkcs11_PK11KeyPairGenerator_generateRSAKeyPairWithOpFlags; Java_org_mozilla_jss_pkcs11_PK11KeyPairGenerator_generateDSAKeyPairWithOpFlags; Java_org_mozilla_jss_CryptoManager_OCSPCacheSettingsNative; Java_org_mozilla_jss_CryptoManager_setOCSPTimeoutNative; Java_org_mozilla_jss_pkcs11_PK11SymmetricKeyDeriver_nativeDeriveSymKey; Java_org_mozilla_jss_pkcs11_PK11SymKey_setNickNameNative; local: *; }; JSS_4.4.1 { # JSS 4.4.1 release global: Java_org_mozilla_jss_pkcs11_PK11Store_importEncryptedPrivateKeyInfo; local: *; }; JSS_4.5 { # JSS 4.5 release global: Java_org_mozilla_jss_pkcs11_PK11RSAPrivateKey_getModulusByteArray; Java_org_mozilla_jss_pkcs11_PK11Token_importPublicKey; Java_org_mozilla_jss_pkcs11_PK11Store_loadPrivateKeys; Java_org_mozilla_jss_pkcs11_PK11Store_loadPublicKeys; Java_org_mozilla_jss_pkcs11_PK11Store_deletePublicKey; Java_org_mozilla_jss_ssl_SSLSocket_boundSSLVersionRange; local: *; }; JSS_4.5.1 { global: Java_org_mozilla_jss_CryptoManager_getJSSMajorVersion; Java_org_mozilla_jss_CryptoManager_getJSSMinorVersion; Java_org_mozilla_jss_CryptoManager_getJSSPatchVersion; local: *; }; JSS_4.5.3 { global: Java_org_mozilla_jss_nss_PR_Open; Java_org_mozilla_jss_nss_PR_Close; Java_org_mozilla_jss_nss_PR_Write; Java_org_mozilla_jss_nss_PR_Read; Java_org_mozilla_jss_nss_PR_Send; Java_org_mozilla_jss_nss_PR_Recv; Java_org_mozilla_jss_nss_PR_NewTCPSocket; Java_org_mozilla_jss_nss_PR_NewBufferPRFD; Java_org_mozilla_jss_nss_PR_Shutdown; Java_org_mozilla_jss_nss_PR_GetError; Java_org_mozilla_jss_nss_PR_GetErrorTextNative; Java_org_mozilla_jss_nss_PR_ErrorToNameNative; Java_org_mozilla_jss_nss_PR_getPRShutdownRcv; Java_org_mozilla_jss_nss_PR_getPRShutdownSend; Java_org_mozilla_jss_nss_PR_getPRShutdownBoth; Java_org_mozilla_jss_nss_PR_getPRSuccess; Java_org_mozilla_jss_nss_PR_getPRFailure; Java_org_mozilla_jss_nss_PRErrors_getWouldBlockError; Java_org_mozilla_jss_nss_SSL_ImportFD; Java_org_mozilla_jss_nss_SSL_OptionSet; Java_org_mozilla_jss_nss_SSL_OptionGet; Java_org_mozilla_jss_nss_SSL_SetURL; Java_org_mozilla_jss_nss_SSL_CipherPrefSet; Java_org_mozilla_jss_nss_SSL_CipherPrefGet; Java_org_mozilla_jss_nss_SSL_VersionRangeSetNative; Java_org_mozilla_jss_nss_SSL_VersionRangeGet; Java_org_mozilla_jss_nss_SSL_SecurityStatus; Java_org_mozilla_jss_nss_SSL_ResetHandshake; Java_org_mozilla_jss_nss_SSL_ForceHandshake; Java_org_mozilla_jss_nss_SSL_ConfigSecureServer; Java_org_mozilla_jss_nss_SSL_ConfigServerCert; Java_org_mozilla_jss_nss_SSL_ConfigServerSessionIDCache; Java_org_mozilla_jss_nss_SSL_PeerCertificate; Java_org_mozilla_jss_nss_SSL_PeerCertificateChain; Java_org_mozilla_jss_nss_SSL_getSSLRequestCertificate; Java_org_mozilla_jss_nss_SSL_getSSLRequireCertificate; Java_org_mozilla_jss_nss_SSL_getSSLSECSuccess; Java_org_mozilla_jss_nss_SSL_getSSLSECFailure; Java_org_mozilla_jss_nss_SSL_getSSLSECWouldBlock; Java_org_mozilla_jss_nss_Buffer_Create; Java_org_mozilla_jss_nss_Buffer_Capacity; Java_org_mozilla_jss_nss_Buffer_CanRead; Java_org_mozilla_jss_nss_Buffer_ReadCapacity; Java_org_mozilla_jss_nss_Buffer_CanWrite; Java_org_mozilla_jss_nss_Buffer_WriteCapacity; Java_org_mozilla_jss_nss_Buffer_Read; Java_org_mozilla_jss_nss_Buffer_Write; Java_org_mozilla_jss_nss_Buffer_Get; Java_org_mozilla_jss_nss_Buffer_Put; Java_org_mozilla_jss_nss_Buffer_Free; local: *; }; JSS_4.6.2 { global: Java_org_mozilla_jss_pkcs11_PK11PrivKey_getPublicKey; Java_org_mozilla_jss_CryptoManager_importDERCertNative; Java_org_mozilla_jss_nss_SSL_AttachClientCertCallback; Java_org_mozilla_jss_CryptoManager_getJSSDebug; Java_org_mozilla_jss_util_GlobalRefProxy_releaseNativeResources; Java_org_mozilla_jss_nss_SSL_EnableAlertLoggingNative; Java_org_mozilla_jss_CryptoManager_verifyCertificateNowNative3; Java_org_mozilla_jss_nss_SSLFDProxy_releaseNativeResources; local: *; }; JSS_4.6.3 { global: Java_org_mozilla_jss_pkcs11_attrs_CKAClass_acquireNativeResources; Java_org_mozilla_jss_pkcs11_attrs_CKAClass_releaseNativeResources; Java_org_mozilla_jss_pkcs11_attrs_CKAKeyType_acquireNativeResources; Java_org_mozilla_jss_pkcs11_attrs_CKAKeyType_releaseNativeResources; Java_org_mozilla_jss_pkcs11_attrs_CKAUsage_acquireNativeResources; Java_org_mozilla_jss_pkcs11_attrs_CKAUsage_releaseNativeResources; Java_org_mozilla_jss_pkcs11_attrs_CKAValueLen_acquireNativeResources; Java_org_mozilla_jss_pkcs11_attrs_CKAValueLen_releaseNativeResources; Java_org_mozilla_jss_pkcs11_PK11KeyGenerator_generateKBKDF; Java_org_mozilla_jss_crypto_KBKDFByteArrayParam_acquireNativeResourcesInternal; Java_org_mozilla_jss_crypto_KBKDFByteArrayParam_releaseNativeResourcesInternal; Java_org_mozilla_jss_crypto_KBKDFCounterParams_acquireNativeResourcesInternal; Java_org_mozilla_jss_crypto_KBKDFCounterParams_releaseNativeResourcesInternal; Java_org_mozilla_jss_crypto_KBKDFDerivedKey_acquireNativeResourcesInternal; Java_org_mozilla_jss_crypto_KBKDFDerivedKey_getKeyFromHandle; Java_org_mozilla_jss_crypto_KBKDFDerivedKey_releaseNativeResourcesInternal; Java_org_mozilla_jss_crypto_KBKDFDKMLengthParam_acquireNativeResources; Java_org_mozilla_jss_crypto_KBKDFDKMLengthParam_releaseNativeResources; Java_org_mozilla_jss_crypto_KBKDFFeedbackParams_acquireNativeResourcesInternal; Java_org_mozilla_jss_crypto_KBKDFFeedbackParams_releaseNativeResourcesInternal; Java_org_mozilla_jss_crypto_KBKDFIterationVariableParam_acquireNativeResources; Java_org_mozilla_jss_crypto_KBKDFIterationVariableParam_releaseNativeResources; Java_org_mozilla_jss_crypto_KBKDFOptionalCounterParam_acquireNativeResources; Java_org_mozilla_jss_crypto_KBKDFOptionalCounterParam_releaseNativeResources; Java_org_mozilla_jss_crypto_KBKDFPipelineParams_acquireNativeResourcesInternal; Java_org_mozilla_jss_crypto_KBKDFPipelineParams_releaseNativeResourcesInternal; Java_org_mozilla_jss_crypto_Policy_getRSAMinimumKeySize; Java_org_mozilla_jss_crypto_Policy_getDHMinimumKeySize; Java_org_mozilla_jss_crypto_Policy_getDSAMinimumKeySize; Java_org_mozilla_jss_nss_SSL_ConfigJSSDefaultCertAuthCallback; Java_org_mozilla_jss_ssl_SSLCipher_checkSupportedStatus; Java_org_mozilla_jss_nss_PRErrors_getSocketShutdownError; local: *; }; JSS_4.7.0 { global: Java_org_mozilla_jss_nss_SSL_GetChannelInfo; Java_org_mozilla_jss_nss_SSL_GetPreliminaryChannelInfo; Java_org_mozilla_jss_nss_SSL_InvalidateSession; Java_org_mozilla_jss_nss_SSL_CipherPrefGetDefault; Java_org_mozilla_jss_nss_SSL_CipherPrefSetDefault; Java_org_mozilla_jss_nss_SSL_VersionRangeGetDefaultNative; Java_org_mozilla_jss_nss_SSL_VersionRangeSetDefaultNative; Java_org_mozilla_jss_util_GlobalRefProxy_refOf; Java_org_mozilla_jss_CryptoManager_shutdownNative; Java_org_mozilla_jss_nss_SSL_RemoveCallbacks; Java_org_mozilla_jss_nss_SSL_getSSLEnablePostHandshakeAuth; Java_org_mozilla_jss_nss_SSL_getSSLEnableRenegotiation; Java_org_mozilla_jss_nss_SSL_getSSLRequireSafeNegotiation; Java_org_mozilla_jss_nss_SSL_getSSLRenegotiateNever; Java_org_mozilla_jss_nss_SSL_getSSLRenegotiateUnrestricted; Java_org_mozilla_jss_nss_SSL_getSSLRenegotiateRequiresXtn; Java_org_mozilla_jss_nss_SSL_getSSLRenegotiateTransitional; Java_org_mozilla_jss_nss_SSL_getSSLEnableFallbackSCSV; Java_org_mozilla_jss_nss_SSL_ReHandshake; Java_org_mozilla_jss_nss_SSL_EnableHandshakeCallback; Java_org_mozilla_jss_nss_SSL_SendCertificateRequest; Java_org_mozilla_jss_nss_SSL_getSSLRequireNever; Java_org_mozilla_jss_nss_SSL_getSSLRequireAlways; Java_org_mozilla_jss_nss_SSL_getSSLRequireFirstHandshake; Java_org_mozilla_jss_nss_SSL_getSSLRequireNoError; Java_org_mozilla_jss_nss_SSL_KeyUpdate; Java_org_mozilla_jss_nss_SSL_ConfigAsyncTrustManagerCertAuthCallback; Java_org_mozilla_jss_nss_SSL_ConfigSyncTrustManagerCertAuthCallback; Java_org_mozilla_jss_nss_SSL_AuthCertificateComplete; Java_org_mozilla_jss_nss_SECErrors_getBadDER; Java_org_mozilla_jss_nss_SECErrors_getExpiredCertificate; Java_org_mozilla_jss_nss_SECErrors_getCertNotValid; Java_org_mozilla_jss_nss_SECErrors_getRevokedCertificateOCSP; Java_org_mozilla_jss_nss_SECErrors_getRevokedCertificate; Java_org_mozilla_jss_nss_SECErrors_getUntrustedIssuer; Java_org_mozilla_jss_nss_SECErrors_getUntrustedCert; local: *; }; JSS_4.7.1 { global: Java_org_mozilla_jss_nss_SSL_ImportFDNative; local: *; }; JSS_4.7.3 { global: Java_org_mozilla_jss_nss_SSL_ConfigAsyncBadCertCallback; Java_org_mozilla_jss_nss_SSL_ConfigSyncBadCertCallback; Java_org_mozilla_jss_nss_SSLErrors_getBadCertDomain; local: *; }; JSS_4.8.1 { global: Java_org_mozilla_jss_crypto_JSSOAEPParameterSpec_acquireNativeResources; Java_org_mozilla_jss_crypto_JSSOAEPParameterSpec_releaseNativeResources; local: *; }; jss-5.0.0/pom.xml000066400000000000000000000034211412550063600136320ustar00rootroot00000000000000 4.0.0 org.dogtagpki jss 5.0.0-SNAPSHOT junit junit 4.13.2 test org.apache.commons commons-lang3 3.11 org.slf4j slf4j-api 1.7.25 org.slf4j slf4j-jdk14 1.7.25 runtime org.apache.maven.plugins maven-compiler-plugin 3.8.1 11 dogtagpki_jss dogtagpki https://sonarcloud.io jss-5.0.0/src/000077500000000000000000000000001412550063600131045ustar00rootroot00000000000000jss-5.0.0/src/broken_test/000077500000000000000000000000001412550063600154235ustar00rootroot00000000000000jss-5.0.0/src/broken_test/java/000077500000000000000000000000001412550063600163445ustar00rootroot00000000000000jss-5.0.0/src/broken_test/java/org/000077500000000000000000000000001412550063600171335ustar00rootroot00000000000000jss-5.0.0/src/broken_test/java/org/mozilla/000077500000000000000000000000001412550063600206025ustar00rootroot00000000000000jss-5.0.0/src/broken_test/java/org/mozilla/jss/000077500000000000000000000000001412550063600214015ustar00rootroot00000000000000jss-5.0.0/src/broken_test/java/org/mozilla/jss/tests/000077500000000000000000000000001412550063600225435ustar00rootroot00000000000000jss-5.0.0/src/broken_test/java/org/mozilla/jss/tests/DirStrConverterTest.java000066400000000000000000000105201412550063600273430ustar00rootroot00000000000000package org.mozilla.jss.tests; import org.junit.Assert; import org.junit.Test; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.x509.DirStrConverter; public class DirStrConverterTest { @Test public void testEmptyString() throws Exception { String string = ""; System.out.println("Converting: [" + string + "]"); byte[] expected = JSSUtil.encode(DerValue.tag_PrintableString, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = ConverterTestUtil.convert(new DirStrConverter(), string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testNullCharacters() throws Exception { String string = StringTestUtil.NULL_CHARS; System.out.println("Converting: [" + StringTestUtil.toString(string.getBytes()) + "]"); byte[] expected = JSSUtil.encode(DerValue.tag_T61String, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = ConverterTestUtil.convert(new DirStrConverter(), string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testPrintableCharacters() throws Exception { String string = StringTestUtil.PRINTABLE_CHARS; System.out.println("Converting: [" + string + "]"); byte[] expected = JSSUtil.encode(DerValue.tag_PrintableString, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = ConverterTestUtil.convert(new DirStrConverter(), string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testControlCharacters() throws Exception { String string = StringTestUtil.CONTROL_CHARS; System.out.println("Converting: [" + StringTestUtil.toString(string.getBytes()) + "]"); byte[] expected = JSSUtil.encode(DerValue.tag_T61String, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = ConverterTestUtil.convert(new DirStrConverter(), string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testMultibyteCharacters() throws Exception { String string = StringTestUtil.MULTIBYTE_CHARS; System.out.println("Converting: [" + string + "]"); byte[] expected = JSSUtil.encode(DerValue.tag_UniversalString, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = ConverterTestUtil.convert(new DirStrConverter(), string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testPrintableCharactersWithTags() throws Exception { String string = StringTestUtil.PRINTABLE_CHARS; System.out.println("Converting: [" + string + "]"); byte[] expected = JSSUtil.encode(DerValue.tag_IA5String, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = ConverterTestUtil.convert(new DirStrConverter(), string, new byte[] { DerValue.tag_IA5String, DerValue.tag_UTF8String }); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testMultibyteCharactersWithTags() throws Exception { String string = StringTestUtil.MULTIBYTE_CHARS; System.out.println("Converting: [" + string + "]"); byte[] expected = JSSUtil.encode(DerValue.tag_UTF8String, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = ConverterTestUtil.convert(new DirStrConverter(), string, new byte[] { DerValue.tag_IA5String, DerValue.tag_UTF8String }); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } } jss-5.0.0/src/broken_test/java/org/mozilla/jss/tests/GenericASN1ExtensionTest.java000066400000000000000000000047271412550063600301540ustar00rootroot00000000000000package org.mozilla.jss.tests; import java.io.ByteArrayOutputStream; import java.io.OutputStream; import java.util.Hashtable; import org.junit.Assert; import org.junit.Test; import org.mozilla.jss.netscape.security.extensions.GenericASN1Extension; import org.mozilla.jss.netscape.security.x509.OIDMap; public class GenericASN1ExtensionTest { //@Test public void testConstructorArgs() throws Exception { String name1 = "testExtension1"; String oid1 = "1.2.3.4"; String pattern = ""; Hashtable config = new Hashtable(); GenericASN1Extension extension1 = new GenericASN1Extension(name1, oid1, pattern, false, config); Assert.assertEquals(name1, extension1.getName()); Assert.assertNotNull(OIDMap.getClass(name1)); String name2 = "testExtension2"; String oid2 = "2.4.6.8"; GenericASN1Extension extension2 = new GenericASN1Extension(name2, oid2, pattern, false, config); Assert.assertEquals(name2, extension2.getName()); Assert.assertNotNull(OIDMap.getClass(name2)); } @Test public void testConstructorJustConfig() throws Exception { String name1 = "testExtension1"; String oid1 = "1.2.3.4"; String pattern = ""; Hashtable config = new Hashtable(); config.put("oid", oid1); config.put("name", name1); config.put("pattern", pattern); config.put("critical", "true"); GenericASN1Extension extension1 = new GenericASN1Extension(config); Assert.assertEquals(name1, extension1.getName()); //Assert.assertNotNull(OIDMap.getClass(name1)); String name2 = "testExtension2"; String oid2 = "2.4.6.8"; config.put("oid", oid2); config.put("name", name2); GenericASN1Extension extension2 = new GenericASN1Extension(config); Assert.assertEquals(name2, extension2.getName()); //Assert.assertNotNull(OIDMap.getClass(name2)); OutputStream outputStream = new ByteArrayOutputStream(); extension1.encode(outputStream); extension2.encode(outputStream); } @Test public void testConstructorDER() throws Exception { byte[] value = new byte[0]; GenericASN1Extension extension = new GenericASN1Extension(true, value); OutputStream outputStream = new ByteArrayOutputStream(); extension.encode(outputStream); } } jss-5.0.0/src/main/000077500000000000000000000000001412550063600140305ustar00rootroot00000000000000jss-5.0.0/src/main/java/000077500000000000000000000000001412550063600147515ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/000077500000000000000000000000001412550063600155405ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/000077500000000000000000000000001412550063600172075ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/000077500000000000000000000000001412550063600200065ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/CRLImportException.java000066400000000000000000000014261412550063600243460ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss; /** * Thrown if a CRL cannot be imported */ public class CRLImportException extends java.lang.Exception { private static final long serialVersionUID = 1L; public CRLImportException() {} public CRLImportException(String mesg) { super(mesg); } public CRLImportException(String mesg, Throwable cause) { super(mesg, cause); } public CRLImportException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(mesg, cause, enableSuppression, writableStackTrace); } } jss-5.0.0/src/main/java/org/mozilla/jss/CertDatabaseException.java000066400000000000000000000015621412550063600250560ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss; /** * This exception is thrown if the certificate database does not exist, * or if an error occurs while opening it. */ public class CertDatabaseException extends java.lang.Exception { private static final long serialVersionUID = 1L; public CertDatabaseException() {} public CertDatabaseException(String mesg) { super(mesg); } public CertDatabaseException(String mesg, Throwable cause) { super(mesg, cause); } public CertDatabaseException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(mesg, cause, enableSuppression, writableStackTrace); } } jss-5.0.0/src/main/java/org/mozilla/jss/CertificateUsage.java000066400000000000000000000122531412550063600240630ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss; import java.util.ArrayList; import java.util.Iterator; /** * CertificateUsage options for validation */ public final class CertificateUsage { private int usage; private int value; private String name; // certificateUsage, these must be kept in sync with nss/lib/certdb/certt.h private static final int certificateUsageCheckAllUsages = 0x0000; private static final int certificateUsageSSLClient = 0x0001; private static final int certificateUsageSSLServer = 0x0002; private static final int certificateUsageSSLServerWithStepUp = 0x0004; private static final int certificateUsageSSLCA = 0x0008; private static final int certificateUsageEmailSigner = 0x0010; private static final int certificateUsageEmailRecipient = 0x0020; private static final int certificateUsageObjectSigner = 0x0040; private static final int certificateUsageUserCertImport = 0x0080; private static final int certificateUsageVerifyCA = 0x0100; private static final int certificateUsageProtectedObjectSigner = 0x0200; private static final int certificateUsageStatusResponder = 0x0400; private static final int certificateUsageAnyCA = 0x0800; private static final int certificateUsageIPsec = 0x1000; // SECCertUsage enum values private static final int certUsageSSLClient = 0; private static final int certUsageSSLServer = 1; private static final int certUsageSSLServerWithStepUp = 2; private static final int certUsageSSLCA = 3; private static final int certUsageEmailSigner = 4; private static final int certUsageEmailRecipient = 5; private static final int certUsageObjectSigner = 6; private static final int certUsageUserCertImport = 7; private static final int certUsageVerifyCA = 8; private static final int certUsageProtectedObjectSigner = 9; private static final int certUsageStatusResponder = 10; private static final int certUsageAnyCA = 11; private static final int certUsageIPsec = 12; static private ArrayList list = new ArrayList<>(); private CertificateUsage() { } private CertificateUsage(int usage, int value, String name) { this.usage = usage; this.value = value; this.name = name; list.add(this); } public int getUsage() { return usage; } static public Iterator getCertificateUsages() { return list.iterator(); } @Override public String toString() { return name; } public int getEnumValue() { return value; } public static final CertificateUsage CheckAllUsages = new CertificateUsage(certificateUsageCheckAllUsages, -1, "CheckAllUsages"); public static final CertificateUsage SSLClient = new CertificateUsage(certificateUsageSSLClient, certUsageSSLClient, "SSLClient"); public static final CertificateUsage SSLServer = new CertificateUsage(certificateUsageSSLServer, certUsageSSLServer, "SSLServer"); public static final CertificateUsage SSLServerWithStepUp = new CertificateUsage(certificateUsageSSLServerWithStepUp, certUsageSSLServerWithStepUp, "SSLServerWithStepUp"); public static final CertificateUsage SSLCA = new CertificateUsage(certificateUsageSSLCA, certUsageSSLCA, "SSLCA"); public static final CertificateUsage EmailSigner = new CertificateUsage(certificateUsageEmailSigner, certUsageEmailSigner, "EmailSigner"); public static final CertificateUsage EmailRecipient = new CertificateUsage(certificateUsageEmailRecipient, certUsageEmailRecipient, "EmailRecipient"); public static final CertificateUsage ObjectSigner = new CertificateUsage(certificateUsageObjectSigner, certUsageObjectSigner, "ObjectSigner"); public static final CertificateUsage UserCertImport = new CertificateUsage(certificateUsageUserCertImport, certUsageUserCertImport, "UserCertImport"); public static final CertificateUsage VerifyCA = new CertificateUsage(certificateUsageVerifyCA, certUsageVerifyCA, "VerifyCA"); public static final CertificateUsage ProtectedObjectSigner = new CertificateUsage(certificateUsageProtectedObjectSigner, certUsageProtectedObjectSigner, "ProtectedObjectSigner"); public static final CertificateUsage StatusResponder = new CertificateUsage(certificateUsageStatusResponder, certUsageStatusResponder, "StatusResponder"); public static final CertificateUsage AnyCA = new CertificateUsage(certificateUsageAnyCA, certUsageAnyCA, "AnyCA"); public static final CertificateUsage IPsec = new CertificateUsage(certificateUsageIPsec, certUsageIPsec, "IPsec"); /* The folllowing usages cannot be verified: certUsageAnyCA certUsageProtectedObjectSigner certUsageUserCertImport certUsageVerifyCA */ public static final int basicCertificateUsages = /*0x0b80;*/ certificateUsageUserCertImport | certificateUsageVerifyCA | certificateUsageProtectedObjectSigner | certificateUsageAnyCA ; } jss-5.0.0/src/main/java/org/mozilla/jss/CryptoManager.c000066400000000000000000000761211412550063600227340ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "_jni/org_mozilla_jss_CryptoManager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pk11util.h" #include #if defined(AIX) || defined(HPUX) #include #endif /** These externs are only here to ** keep certain compilers from optimizing the ** version info away. */ #include "util/jssver.h" extern const char __jss_base_rcsid[]; extern const char __jss_base_sccsid[]; const char * jss_rcsid() { return __jss_base_rcsid; } const char * jss_sccsid() { return __jss_base_sccsid; } /********************************************************************/ /* The VERSION Strings should be updated everytime a new release */ /* of JSS is generated. Note that this is done by changing */ /* cmake/JSSConfig.cmake. */ /********************************************************************/ /* JSS_VERSION from mozilla/security/jss/org/mozilla/jss/util/jssver.h */ static const char* VARIABLE_MAY_NOT_BE_USED DLL_JSS_VERSION = "JSS_VERSION = " JSS_VERSION; /* NSS_VERSION from mozilla/security/nss/lib/nss/nss.h */ static const char* VARIABLE_MAY_NOT_BE_USED DLL_NSS_VERSION = "NSS_VERSION = " NSS_VERSION; /* NSPR_version from mozilla/nsprpub/pr/include/prinit.h */ static const char* VARIABLE_MAY_NOT_BE_USED DLL_NSPR_VERSION = "NSPR_VERSION = " PR_VERSION; static jobject makePWCBInfo(JNIEnv *env, PK11SlotInfo *slot); static char* getPWFromCallback(PK11SlotInfo *slot, PRBool retry, void *arg); /************************************************************* * AIX and HP signal handling madness * * In order for the JVM, kernel, and NSPR to work together, we setup * a signal handler for SIGCHLD that does nothing. This is only done * on AIX and HP. *************************************************************/ #if defined(AIX) || defined(HPUX) static PRStatus handleSigChild(JNIEnv *env) { struct sigaction action; sigset_t signalset; int result; sigemptyset(&signalset); action.sa_handler = SIG_DFL; action.sa_mask = signalset; action.sa_flags = 0; result = sigaction( SIGCHLD, &action, NULL ); if( result != 0 ) { JSS_throwMsg(env, GENERAL_SECURITY_EXCEPTION, "Failed to set SIGCHLD handler"); return PR_FAILURE; } return PR_SUCCESS; } #endif int ConfigureOCSP( JNIEnv *env, jboolean ocspCheckingEnabled, jstring ocspResponderURL, jstring ocspResponderCertNickname ) { const char *ocspResponderURL_string = NULL; const char *ocspResponderCertNickname_string = NULL; SECStatus status; int result = SECSuccess; CERTCertDBHandle *certdb = CERT_GetDefaultCertDB(); /* if caller specified default responder, get the * strings associated with these args */ ocspResponderURL_string = JSS_RefJString(env, ocspResponderURL); ocspResponderCertNickname_string = JSS_RefJString(env, ocspResponderCertNickname); /* first disable OCSP - we'll enable it later */ CERT_DisableOCSPChecking(certdb); /* if they set the default responder, then set it up * and enable it */ if (ocspResponderURL_string) { /* if ocspResponderURL is set they must specify the ocspResponderCertNickname */ if (ocspResponderCertNickname == NULL ) { JSS_throwMsg(env, GENERAL_SECURITY_EXCEPTION, "if OCSP responderURL is set, the Responder Cert nickname must be set"); result = SECFailure; goto finish; } else { CERTCertificate *cert; /* if the nickname is set */ cert = CERT_FindCertByNickname(certdb, ocspResponderCertNickname_string); if (cert == NULL) { /* * look for the cert on an external token. */ cert = PK11_FindCertFromNickname(ocspResponderCertNickname_string, NULL); } if (cert == NULL) { JSS_throwMsg(env, GENERAL_SECURITY_EXCEPTION, "Unable to find the OCSP Responder Certificate nickname."); result = SECFailure; goto finish; } CERT_DestroyCertificate(cert); } status = CERT_SetOCSPDefaultResponder( certdb, ocspResponderURL_string, ocspResponderCertNickname_string ); if (status == SECFailure) { /* deal with error */ JSS_throwMsg(env, GENERAL_SECURITY_EXCEPTION, "OCSP Could not set responder"); result = SECFailure; goto finish; } CERT_EnableOCSPDefaultResponder(certdb); } else if (ocspResponderURL == NULL) { /* if no defaultresponder is set, disable it */ CERT_DisableOCSPDefaultResponder(certdb); } /* enable OCSP checking if requested */ if (ocspCheckingEnabled) { CERT_EnableOCSPChecking(certdb); } finish: JSS_DerefJString(env, ocspResponderURL, ocspResponderURL_string); JSS_DerefJString(env, ocspResponderCertNickname, ocspResponderCertNickname_string); return result; } /********************************************************************** * This is the PasswordCallback object that will be used to login * to tokens implicitly. */ static jobject globalPasswordCallback = NULL; /********************************************************************** * The Java virtual machine can be used to retrieve the JNI environment * pointer from callback functions. */ JavaVM * JSS_javaVM = NULL; JNIEXPORT void JNICALL Java_org_mozilla_jss_CryptoManager_initializeAllNative (JNIEnv *env, jclass clazz, jstring configDir, jstring certPrefix, jstring keyPrefix, jstring secmodName, jboolean readOnly, jstring manuString, jstring libraryString, jstring tokString, jstring keyTokString, jstring slotString, jstring keySlotString, jstring fipsString, jstring fipsKeyString, jboolean ocspCheckingEnabled, jstring ocspResponderURL, jstring ocspResponderCertNickname, jboolean initializeJavaOnly, jboolean PKIXVerify, jboolean noCertDB, jboolean noModDB, jboolean forceOpen, jboolean noRootInit, jboolean optimizeSpace, jboolean PK11ThreadSafe, jboolean PK11Reload, jboolean noPK11Finalize, jboolean cooperate) { Java_org_mozilla_jss_CryptoManager_initializeAllNative2( env, clazz, configDir, certPrefix, keyPrefix, secmodName, readOnly, manuString, libraryString, tokString, keyTokString, slotString, keySlotString, fipsString, fipsKeyString, ocspCheckingEnabled, ocspResponderURL, ocspResponderCertNickname, JNI_FALSE, /*initializeJavaOnly*/ PKIXVerify, noCertDB, noModDB, forceOpen, noRootInit, optimizeSpace, PK11ThreadSafe, PK11Reload, noPK11Finalize, cooperate); } JNIEXPORT void JNICALL Java_org_mozilla_jss_CryptoManager_initializeAllNative2 (JNIEnv *env, jclass clazz, jstring configDir, jstring certPrefix, jstring keyPrefix, jstring secmodName, jboolean readOnly, jstring manuString, jstring libraryString, jstring tokString, jstring keyTokString, jstring slotString, jstring keySlotString, jstring fipsString, jstring fipsKeyString, jboolean ocspCheckingEnabled, jstring ocspResponderURL, jstring ocspResponderCertNickname, jboolean initializeJavaOnly, jboolean PKIXVerify, jboolean noCertDB, jboolean noModDB, jboolean forceOpen, jboolean noRootInit, jboolean optimizeSpace, jboolean PK11ThreadSafe, jboolean PK11Reload, jboolean noPK11Finalize, jboolean cooperate) { SECStatus rv = SECFailure; const char *szConfigDir = NULL; const char *szCertPrefix = NULL; const char *szKeyPrefix = NULL; const char *szSecmodName = NULL; const char *manuChars = NULL; const char *libraryChars = NULL; const char *tokChars = NULL; const char *keyTokChars = NULL; const char *slotChars = NULL; const char *keySlotChars = NULL; const char *fipsChars = NULL; const char *fipsKeyChars = NULL; PRUint32 initFlags; /* This is thread-safe because initialize is synchronized */ static PRBool initialized=PR_FALSE; if( configDir == NULL || manuString == NULL || libraryString == NULL || tokString == NULL || keyTokString == NULL || slotString == NULL || keySlotString == NULL || fipsString == NULL || fipsKeyString == NULL ) { JSS_throw(env, NULL_POINTER_EXCEPTION); goto finish; } /* Make sure initialize() completes only once */ if(initialized) { JSS_throw(env, ALREADY_INITIALIZED_EXCEPTION); goto finish; } /* * Save the JavaVM pointer so we can retrieve the JNI environment * later. This only works if there is only one Java VM. */ if( (*env)->GetJavaVM(env, &JSS_javaVM) != 0 ) { JSS_trace(env, JSS_TRACE_ERROR, "Unable to to access Java virtual machine"); PR_ASSERT(PR_FALSE); goto finish; } /* * Initialize the errcode translation table. */ JSS_initErrcodeTranslationTable(); /* * The rest of the initialization (the NSS stuff) is skipped if * the initializeJavaOnly flag is set. */ if( initializeJavaOnly) { initialized = PR_TRUE; goto finish; } /* * Set the PKCS #11 strings */ manuChars = JSS_RefJString(env, manuString); libraryChars = JSS_RefJString(env, libraryString); tokChars = JSS_RefJString(env, tokString); keyTokChars = JSS_RefJString(env, keyTokString); slotChars = JSS_RefJString(env, slotString); keySlotChars = JSS_RefJString(env, keySlotString); fipsChars = JSS_RefJString(env, fipsString); fipsKeyChars = JSS_RefJString(env, fipsKeyString); if( (*env)->ExceptionOccurred(env) ) { ASSERT_OUTOFMEM(env); goto finish; } PR_ASSERT( strlen(manuChars) == 33 ); PR_ASSERT( strlen(libraryChars) == 33 ); PR_ASSERT( strlen(tokChars) == 33 ); PR_ASSERT( strlen(keyTokChars) == 33 ); PR_ASSERT( strlen(slotChars) == 65 ); PR_ASSERT( strlen(keySlotChars) == 65 ); PR_ASSERT( strlen(fipsChars) == 65 ); PR_ASSERT( strlen(fipsKeyChars) == 65 ); PK11_ConfigurePKCS11( manuChars, libraryChars, tokChars, keyTokChars, slotChars, keySlotChars, fipsChars, fipsKeyChars, 0, /* minimum pin length */ PR_FALSE /* password required */ ); szConfigDir = JSS_RefJString(env, configDir); if( certPrefix != NULL || keyPrefix != NULL || secmodName != NULL || noCertDB || noModDB || forceOpen || noRootInit || optimizeSpace || PK11ThreadSafe || PK11Reload || noPK11Finalize || cooperate) { /* * Set up arguments to NSS_Initialize */ szCertPrefix = JSS_RefJString(env, certPrefix); szKeyPrefix = JSS_RefJString(env, keyPrefix); szSecmodName = JSS_RefJString(env, secmodName); initFlags = 0; if( readOnly ) { initFlags |= NSS_INIT_READONLY; } if( noCertDB ) { initFlags |= NSS_INIT_NOCERTDB; } if( noModDB ) { initFlags |= NSS_INIT_NOMODDB; } if( forceOpen ) { initFlags |= NSS_INIT_FORCEOPEN; } if( noRootInit ) { initFlags |= NSS_INIT_NOROOTINIT; } if( optimizeSpace ) { initFlags |= NSS_INIT_OPTIMIZESPACE; } if( PK11ThreadSafe ) { initFlags |= NSS_INIT_PK11THREADSAFE; } if( PK11Reload ) { initFlags |= NSS_INIT_PK11RELOAD; } if( noPK11Finalize ) { initFlags |= NSS_INIT_NOPK11FINALIZE; } if( cooperate ) { initFlags |= NSS_INIT_COOPERATE; } /* * Initialize NSS. */ rv = NSS_Initialize(szConfigDir, szCertPrefix, szKeyPrefix, szSecmodName, initFlags); } else { if( readOnly ) { rv = NSS_Init(szConfigDir); } else { rv = NSS_InitReadWrite(szConfigDir); } } if( rv != SECSuccess ) { JSS_throwMsgPrErr(env, SECURITY_EXCEPTION, "Unable to initialize security library"); goto finish; } /* Register additional OIDs, see Algorithm.c */ rv = JSS_RegisterDynamicOids(); if( rv != SECSuccess ) { JSS_throwMsgPrErr(env, SECURITY_EXCEPTION, "Unable to ad dynamic oids" ); goto finish; } /* * Set default password callback. This is the only place this * should ever be called if you are using Ninja. */ PK11_SetPasswordFunc(getPWFromCallback); /* * Setup NSS to call the specified OCSP responder */ rv = ConfigureOCSP( env, ocspCheckingEnabled, ocspResponderURL, ocspResponderCertNickname ); if (rv != SECSuccess) { goto finish; } /* * Set up policy. We're always domestic now. Thanks to the US Government! */ if( NSS_SetDomesticPolicy() != SECSuccess ) { JSS_throwMsg(env, SECURITY_EXCEPTION, "Unable to set security policy"); goto finish; } if ( PKIXVerify ) { CERT_SetUsePKIXForValidation(PR_TRUE); } initialized = PR_TRUE; finish: JSS_DerefJString(env, configDir, szConfigDir); JSS_DerefJString(env, certPrefix, szCertPrefix); JSS_DerefJString(env, keyPrefix, szKeyPrefix); JSS_DerefJString(env, secmodName, szSecmodName); JSS_DerefJString(env, manuString, manuChars); JSS_DerefJString(env, libraryString, libraryChars); JSS_DerefJString(env, tokString, tokChars); JSS_DerefJString(env, keyTokString, keyTokChars); JSS_DerefJString(env, slotString, slotChars); JSS_DerefJString(env, keySlotString, keySlotChars); JSS_DerefJString(env, fipsString, fipsChars); JSS_DerefJString(env, fipsKeyString, fipsKeyChars); return; } /********************************************************************** * * JSS_setPasswordCallback * * Sets the global PasswordCallback object, which will be used to * login to tokens implicitly if necessary. * */ void JSS_setPasswordCallback(JNIEnv *env, jobject callback) { PR_ASSERT(env != NULL); /* Free the previously-registered password callback */ if( globalPasswordCallback != NULL ) { (*env)->DeleteGlobalRef(env, globalPasswordCallback); globalPasswordCallback = NULL; } if (callback != NULL) { /* Store the new password callback */ globalPasswordCallback = (*env)->NewGlobalRef(env, callback); if (globalPasswordCallback == NULL) { JSS_throw(env, OUT_OF_MEMORY_ERROR); } } } /********************************************************************** * * CryptoManager.setNativePasswordCallback * * Sets the global PasswordCallback object, which will be used to * login to tokens implicitly if necessary. * */ JNIEXPORT void JNICALL Java_org_mozilla_jss_CryptoManager_setNativePasswordCallback (JNIEnv *env, jclass clazz, jobject callback) { JSS_setPasswordCallback(env, callback); } /******************************************************************** * * g e t P W F r o m C a l l b a c k * * Extracts a password from a password callback and returns * it to PKCS #11. * * INPUTS * slot * The PK11SlotInfo* for the slot we are logging into. * retry * PR_TRUE if this is the first time we are trying to login, * PR_FALSE if we tried before and our password was wrong. * arg * This can contain a Java PasswordCallback object reference, * or NULL to use the default password callback. * RETURNS * The password as extracted from the callback, or NULL if the * callback gives up. */ static char* getPWFromCallback(PK11SlotInfo *slot, PRBool retry, void *arg) { jobject pwcbInfo; jobject pwObject; jbyteArray pwArray=NULL; char* pwchars; char* returnchars=NULL; jclass callbackClass; jclass passwordClass; jmethodID getPWMethod; jmethodID getByteCopyMethod; jmethodID clearMethod; jthrowable exception; jobject callback; JNIEnv *env; PR_ASSERT(slot!=NULL); if(slot==NULL) { return NULL; } /* Get the callback from the arg, or use the default */ PR_ASSERT(sizeof(void*) == sizeof(jobject)); callback = (jobject)arg; if(callback == NULL) { callback = globalPasswordCallback; if(callback == NULL) { /* No global password callback set, no way to get a password */ return NULL; } } /* Get the JNI environment */ if((*JSS_javaVM)->AttachCurrentThread(JSS_javaVM, (void**)&env, NULL) != 0){ PR_ASSERT(PR_FALSE); goto finish; } PR_ASSERT(env != NULL); /***************************************** * Construct the JSS_PasswordCallbackInfo *****************************************/ pwcbInfo = makePWCBInfo(env, slot); if(pwcbInfo==NULL) { goto finish; } /***************************************** * Get the callback class and methods *****************************************/ callbackClass = (*env)->GetObjectClass(env, callback); if(callbackClass == NULL) { JSS_trace(env, JSS_TRACE_ERROR, "Failed to find password " "callback class"); PR_ASSERT(PR_FALSE); } if(retry) { getPWMethod = (*env)->GetMethodID( env, callbackClass, PW_CALLBACK_GET_PW_AGAIN_NAME, PW_CALLBACK_GET_PW_AGAIN_SIG); } else { getPWMethod = (*env)->GetMethodID( env, callbackClass, PW_CALLBACK_GET_PW_FIRST_NAME, PW_CALLBACK_GET_PW_FIRST_SIG); } if(getPWMethod == NULL) { JSS_trace(env, JSS_TRACE_ERROR, "Failed to find password callback accessor method"); ASSERT_OUTOFMEM(env); goto finish; } /***************************************** * Get the password from the callback *****************************************/ pwObject = (*env)->CallObjectMethod( env, callback, getPWMethod, pwcbInfo); if( (*env)->ExceptionOccurred(env) != NULL) { goto finish; } if( pwObject == NULL ) { JSS_throw(env, GIVE_UP_EXCEPTION); goto finish; } /***************************************** * Get Password class and methods *****************************************/ passwordClass = (*env)->GetObjectClass(env, pwObject); if(passwordClass == NULL) { JSS_trace(env, JSS_TRACE_ERROR, "Failed to find Password class"); ASSERT_OUTOFMEM(env); goto finish; } getByteCopyMethod = (*env)->GetMethodID( env, passwordClass, PW_GET_BYTE_COPY_NAME, PW_GET_BYTE_COPY_SIG); clearMethod = (*env)->GetMethodID( env, passwordClass, PW_CLEAR_NAME, PW_CLEAR_SIG); if(getByteCopyMethod==NULL || clearMethod==NULL) { JSS_trace(env, JSS_TRACE_ERROR, "Failed to find Password manipulation methods from native " "implementation"); ASSERT_OUTOFMEM(env); goto finish; } /************************************************ * Get the bytes from the password, then clear it ***********************************************/ pwArray = (*env)->CallObjectMethod( env, pwObject, getByteCopyMethod); (*env)->CallVoidMethod(env, pwObject, clearMethod); exception = (*env)->ExceptionOccurred(env); if(exception == NULL) { PR_ASSERT(pwArray != NULL); /************************************************************* * Copy the characters out of the byte array, * then erase it *************************************************************/ pwchars = (char*) (*env)->GetByteArrayElements(env, pwArray, NULL); PR_ASSERT(pwchars!=NULL); returnchars = PL_strdup(pwchars); JSS_wipeCharArray(pwchars); JSS_DerefByteArray(env, pwArray, pwchars, 0); } else { returnchars = NULL; } finish: #ifdef DEBUG if( (exception=(*env)->ExceptionOccurred(env)) != NULL) { jclass giveupClass; jmethodID printStackTrace; jclass excepClass; (*env)->ExceptionClear(env); giveupClass = (*env)->FindClass(env, GIVE_UP_EXCEPTION); PR_ASSERT(giveupClass != NULL); if( ! (*env)->IsInstanceOf(env, exception, giveupClass) ) { excepClass = (*env)->GetObjectClass(env, exception); printStackTrace = (*env)->GetMethodID(env, excepClass, "printStackTrace", "()V"); (*env)->CallVoidMethod(env, exception, printStackTrace); PR_ASSERT( PR_FALSE ); } PR_ASSERT(returnchars==NULL); } #else if( ((*env)->ExceptionOccurred(env)) != NULL) { (*env)->ExceptionClear(env); } #endif return returnchars; } /********************************************************************** * * m a k e P W C B I n f o * * Creates a Java PasswordCallbackInfo structure from a PKCS #11 token. * Returns this object, or NULL if an exception was thrown. */ static jobject makePWCBInfo(JNIEnv *env, PK11SlotInfo *slot) { jclass infoClass; jmethodID constructor; jstring name; jobject pwcbInfo=NULL; PR_ASSERT(env!=NULL && slot!=NULL); /***************************************** * Turn the token name into a Java String *****************************************/ name = (*env)->NewStringUTF(env, PK11_GetTokenName(slot)); if(name == NULL) { ASSERT_OUTOFMEM(env); goto finish; } /***************************************** * Look up the class and constructor *****************************************/ infoClass = (*env)->FindClass(env, TOKEN_CBINFO_CLASS_NAME); if(infoClass == NULL) { JSS_trace(env, JSS_TRACE_ERROR, "Unable to find TokenCallbackInfo " "class"); ASSERT_OUTOFMEM(env); goto finish; } constructor = (*env)->GetMethodID( env, infoClass, TOKEN_CBINFO_CONSTRUCTOR_NAME, TOKEN_CBINFO_CONSTRUCTOR_SIG); if(constructor == NULL) { JSS_trace(env, JSS_TRACE_ERROR, "Unable to find " "TokenCallbackInfo constructor"); ASSERT_OUTOFMEM(env); goto finish; } /***************************************** * Create the CallbackInfo object *****************************************/ pwcbInfo = (*env)->NewObject(env, infoClass, constructor, name); if(pwcbInfo == NULL) { JSS_trace(env, JSS_TRACE_ERROR, "Unable to create TokenCallbackInfo"); ASSERT_OUTOFMEM(env); } finish: return pwcbInfo; } /********************************************************************** * CryptoManager.putModulesInVector * * Wraps all PKCS #11 modules in PK11Module Java objects, then puts * these into a Vector. */ JNIEXPORT void JNICALL Java_org_mozilla_jss_CryptoManager_putModulesInVector (JNIEnv *env, jobject this, jobject vector) { SECMODListLock *listLock=NULL; SECMODModuleList *list; SECMODModule *modp=NULL; jclass vectorClass; jmethodID addElement; jobject module; PR_ASSERT(env!=NULL && this!=NULL && vector!=NULL); /*************************************************** * Get JNI ids ***************************************************/ vectorClass = (*env)->GetObjectClass(env, vector); if(vectorClass == NULL) goto finish; addElement = (*env)->GetMethodID(env, vectorClass, VECTOR_ADD_ELEMENT_NAME, VECTOR_ADD_ELEMENT_SIG); if(addElement==NULL) goto finish; /*************************************************** * Lock the list ***************************************************/ listLock = SECMOD_GetDefaultModuleListLock(); PR_ASSERT(listLock!=NULL); SECMOD_GetReadLock(listLock); /*************************************************** * Loop over the modules, adding each one to the vector ***************************************************/ for( list = SECMOD_GetDefaultModuleList(); list != NULL; list=list->next) { PR_ASSERT(list->module != NULL); /** Make a PK11Module **/ modp = SECMOD_ReferenceModule(list->module); module = JSS_PK11_wrapPK11Module(env, &modp); PR_ASSERT(modp==NULL); if(module == NULL) { goto finish; } /** Stick the PK11Module in the Vector **/ (*env)->CallVoidMethod(env, vector, addElement, module); } finish: /*** Unlock the list ***/ if(listLock != NULL) { SECMOD_ReleaseReadLock(listLock); } /*** Free this module if it wasn't properly Java-ized ***/ if(modp!=NULL) { SECMOD_DestroyModule(modp); } return; } /********************************************************************** * CryptoManager.enableFIPS * * Enables or disables FIPS mode. * INPUTS * fips * true means turn on FIPS mode, false means turn it off. * RETURNS * true if a switch happened, false if the library was already * in the requested mode. * THROWS * java.security.GeneralSecurityException if an error occurred with * the PKCS #11 library. */ JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_CryptoManager_enableFIPS (JNIEnv *env, jclass clazz, jboolean fips) { char *name=NULL; jboolean switched = JNI_FALSE; SECStatus status = SECSuccess; if( ((fips==JNI_TRUE) && !PK11_IsFIPS()) || ((fips==JNI_FALSE) && PK11_IsFIPS()) ) { name = PL_strdup(SECMOD_GetInternalModule()->commonName); status = SECMOD_DeleteInternalModule(name); PR_Free(name); switched = JNI_TRUE; } if(status != SECSuccess) { JSS_throwMsgPortErr(env, GENERAL_SECURITY_EXCEPTION, "Failed to toggle FIPS mode"); } return switched; } /*********************************************************************** * CryptoManager.FIPSEnabled * * Returns true if FIPS mode is currently on, false if it ain't. */ JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_CryptoManager_FIPSEnabled(JNIEnv *env, jobject this) { if( PK11_IsFIPS() ) { return JNI_TRUE; } else { return JNI_FALSE; } } /*********************************************************************** * DatabaseCloser.closeDatabases * * Closes the cert and key database, rendering the security library * unusable. */ JNIEXPORT void JNICALL Java_org_mozilla_jss_DatabaseCloser_closeDatabases (JNIEnv *env, jobject this) { NSS_Shutdown(); } /********************************************************************** * configureOCSPNative * * Allows configuration of the OCSP responder during runtime. */ JNIEXPORT void JNICALL Java_org_mozilla_jss_CryptoManager_configureOCSPNative( JNIEnv *env, jobject this, jboolean ocspCheckingEnabled, jstring ocspResponderURL, jstring ocspResponderCertNickname ) { SECStatus rv = SECFailure; rv = ConfigureOCSP(env,ocspCheckingEnabled, ocspResponderURL, ocspResponderCertNickname); if (rv != SECSuccess) { JSS_throwMsgPrErr(env, GENERAL_SECURITY_EXCEPTION, "Failed to configure OCSP"); } } /********************************************************************** * OCSPCacheSettingsNative * * Allows configuration of the OCSP responder cache during runtime. */ JNIEXPORT void JNICALL Java_org_mozilla_jss_CryptoManager_OCSPCacheSettingsNative( JNIEnv *env, jobject this, jint ocsp_cache_size, jint ocsp_min_cache_entry_duration, jint ocsp_max_cache_entry_duration) { SECStatus rv = SECFailure; rv = CERT_OCSPCacheSettings( ocsp_cache_size, ocsp_min_cache_entry_duration, ocsp_max_cache_entry_duration); if (rv != SECSuccess) { JSS_throwMsgPrErrArg(env, GENERAL_SECURITY_EXCEPTION, "Failed to set OCSP cache: error", PORT_GetError()); } } JNIEXPORT void JNICALL Java_org_mozilla_jss_CryptoManager_setOCSPTimeoutNative( JNIEnv *env, jobject this, jint ocsp_timeout ) { SECStatus rv = SECFailure; rv = CERT_SetOCSPTimeout(ocsp_timeout); if (rv != SECSuccess) { JSS_throwMsgPrErrArg(env, GENERAL_SECURITY_EXCEPTION, "Failed to set OCSP timeout: error ", PORT_GetError()); } } JNIEXPORT int JNICALL Java_org_mozilla_jss_CryptoManager_getJSSMajorVersion( JNIEnv *env, jobject this) { return JSS_VMAJOR; } JNIEXPORT int JNICALL Java_org_mozilla_jss_CryptoManager_getJSSMinorVersion( JNIEnv * env, jobject this) { return JSS_VMINOR; } JNIEXPORT int JNICALL Java_org_mozilla_jss_CryptoManager_getJSSPatchVersion( JNIEnv *env, jobject this) { return JSS_VPATCH; } JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_CryptoManager_getJSSDebug(JNIEnv *env, jobject this) { #ifdef DEBUG return JNI_TRUE; #else return JNI_FALSE; #endif } JNIEXPORT void JNICALL Java_org_mozilla_jss_CryptoManager_shutdownNative(JNIEnv *env, jobject this) { if (NSS_IsInitialized()) { NSS_Shutdown(); } } jss-5.0.0/src/main/java/org/mozilla/jss/CryptoManager.java000066400000000000000000001570361412550063600234400ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss; import java.security.GeneralSecurityException; import java.security.Security; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.util.ArrayList; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.Vector; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.crypto.Algorithm; import org.mozilla.jss.crypto.AlreadyInitializedException; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.InternalCertificate; import org.mozilla.jss.crypto.NoSuchItemOnTokenException; import org.mozilla.jss.crypto.ObjectNotFoundException; import org.mozilla.jss.crypto.SignatureAlgorithm; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.crypto.TokenSupplier; import org.mozilla.jss.crypto.TokenSupplierManager; import org.mozilla.jss.crypto.X509Certificate; import org.mozilla.jss.pkcs11.KeyType; import org.mozilla.jss.pkcs11.PK11Cert; import org.mozilla.jss.pkcs11.PK11Module; import org.mozilla.jss.pkcs11.PK11SecureRandom; import org.mozilla.jss.pkcs11.PK11Token; import org.mozilla.jss.provider.java.security.JSSMessageDigestSpi; import org.mozilla.jss.util.InvalidNicknameException; import org.mozilla.jss.util.NativeProxy; import org.mozilla.jss.util.PasswordCallback; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This class is the starting poing for the crypto package. * Use it to initialize the subsystem and to lookup certs, keys, and tokens. * Initialization is done with static methods, and must be done before * an instance can be created. All other operations are done with instance * methods. * @version $Revision$ $Date$ */ public final class CryptoManager implements TokenSupplier { public static Logger logger = LoggerFactory.getLogger(CryptoManager.class); static { logger.debug("CryptoManager: loading JSS library"); try { System.loadLibrary("jss"); logger.debug("CryptoManager: loaded JSS library from java.library.path"); } catch (UnsatisfiedLinkError e) { try { System.load("/usr/lib64/jss/libjss.so"); logger.debug("CryptoManager: loaded JSS library from /usr/lib64/jss/libjss.so"); } catch (UnsatisfiedLinkError e1) { try { System.load("/usr/lib/jss/libjss.so"); logger.debug("CryptoManager: loaded JSS library from /usr/lib/jss/libjss.so"); } catch (UnsatisfiedLinkError e2) { logger.warn("Unable to load jss via loadLibrary: " + e.toString()); logger.warn("Unable to load /usr/lib64/jss/libjss.so: " + e1.toString()); throw e2; } } } } /** * note: this is obsolete in NSS * CertUsage options for validation */ public final static class CertUsage { static private ArrayList list = new ArrayList<>(); private int usage; private String name; private CertUsage() { } private CertUsage(int usage, String name) { this.usage = usage; this.name = name; list.add(this); } public int getUsage() { return usage; } static public Iterator getCertUsages() { return list.iterator(); } @Override public String toString() { return name; } // certUsage, these must be kept in sync with nss/lib/certdb/certt.h public static final CertUsage SSLClient = new CertUsage(0, "SSLClient"); public static final CertUsage SSLServer = new CertUsage(1, "SSLServer"); public static final CertUsage SSLServerWithStepUp = new CertUsage(2, "SSLServerWithStepUp"); public static final CertUsage SSLCA = new CertUsage(3, "SSLCA"); public static final CertUsage EmailSigner = new CertUsage(4, "EmailSigner"); public static final CertUsage EmailRecipient = new CertUsage(5, "EmailRecipient"); public static final CertUsage ObjectSigner = new CertUsage(6, "ObjectSigner"); public static final CertUsage UserCertImport = new CertUsage(7, "UserCertImport"); public static final CertUsage VerifyCA = new CertUsage(8, "VerifyCA"); public static final CertUsage ProtectedObjectSigner = new CertUsage(9, "ProtectedObjectSigner"); public static final CertUsage StatusResponder = new CertUsage(10, "StatusResponder"); public static final CertUsage AnyCA = new CertUsage(11, "AnyCA"); } //////////////////////////////////////////////////// // Module and Token Management //////////////////////////////////////////////////// /** * Retrieves the internal cryptographic services token. This is the * token built into NSS that performs bulk * cryptographic operations. *

In FIPS mode, the internal cryptographic services token is the * same as the internal key storage token. * * @return The internal cryptographic services token. */ @Override public synchronized CryptoToken getInternalCryptoToken() { return internalCryptoToken; } /** * Retrieves the internal key storage token. This is the token * provided by NSS to store private keys. * The keys stored in this token are stored in an encrypted key database. *

In FIPS mode, the internal key storage token is the same as * the internal cryptographic services token. * * @return The internal key storage token. */ public synchronized CryptoToken getInternalKeyStorageToken() { return internalKeyStorageToken; } /** * Looks up the CryptoToken with the given name. Searches all * loaded cryptographic modules for the token. * * @param name The name of the token. * @return The token. * @exception org.mozilla.jss.NoSuchTokenException If no token * is found with the given name. */ public synchronized CryptoToken getTokenByName(String name) throws NoSuchTokenException { Enumeration tokens = getAllTokens(); CryptoToken token; while(tokens.hasMoreElements()) { token = tokens.nextElement(); try { if( name.equals(token.getName()) ) { return token; } } catch( TokenException e ) { throw new RuntimeException(e); } } throw new NoSuchTokenException("No such token: " + name); } /** * Retrieves all tokens that support the given algorithm. * * @param alg Algorithm. * @return Enumeration of tokens. */ public synchronized Enumeration getTokensSupportingAlgorithm(Algorithm alg) { Enumeration tokens = getAllTokens(); Vector goodTokens = new Vector<>(); CryptoToken tok; while(tokens.hasMoreElements()) { tok = tokens.nextElement(); if( tok.doesAlgorithm(alg) ) { goodTokens.addElement(tok); } } return goodTokens.elements(); } /** * Retrieves all tokens. This is an enumeration of all tokens on all * modules. * * @return All tokens accessible from JSS. Each item of the enumeration * is a CryptoToken * @see org.mozilla.jss.crypto.CryptoToken */ public synchronized Enumeration getAllTokens() { Enumeration modules = getModules(); Enumeration tokens; Vector allTokens = new Vector<>(); while(modules.hasMoreElements()) { tokens = modules.nextElement().getTokens(); while(tokens.hasMoreElements()) { allTokens.addElement( tokens.nextElement() ); } } return allTokens.elements(); } /** * Retrieves all tokens except those built into NSS. * This excludes the internal token and the internal * key storage token (which are one and the same in FIPS mode). * * @return All tokens accessible from JSS, except for the built-in * internal tokens. */ public synchronized Enumeration getExternalTokens() { Enumeration modules = getModules(); Enumeration tokens; PK11Token token; Vector allTokens = new Vector<>(); while(modules.hasMoreElements()) { tokens = modules.nextElement().getTokens(); while(tokens.hasMoreElements()) { token = (PK11Token) tokens.nextElement(); if( ! token.isInternalCryptoToken() && ! token.isInternalKeyStorageToken() ) { allTokens.addElement( token ); } } } return allTokens.elements(); } /** * Retrieves all installed cryptographic modules. * * @return An enumeration of all installed PKCS #11 modules. Each * item in the enumeration is a PK11Module. * @see org.mozilla.jss.pkcs11.PK11Module */ public synchronized Enumeration getModules() { return moduleVector.elements(); } // Need to reload modules after adding new one //public native addModule(String name, String libraryName); /** * The list of modules. This should be initialized by the constructor * and updated whenever 1) a new module is added, 2) a module is deleted, * or 3) FIPS mode is switched. */ private Vector moduleVector; /** * Re-creates the Vector of modules that is stored by CryptoManager. * This entails going into native code to enumerate all modules, * wrap each one in a PK11Module, and storing the PK11Module in the vector. */ private synchronized void reloadModules() { moduleVector = new Vector<>(); putModulesInVector(moduleVector); // Get the internal tokens Enumeration tokens = getAllTokens(); internalCryptoToken = null; internalKeyStorageToken = null; while(tokens.hasMoreElements()) { PK11Token token = (PK11Token) tokens.nextElement(); if( token.isInternalCryptoToken() ) { assert(internalCryptoToken == null); internalCryptoToken = token; } if( token.isInternalKeyStorageToken() ) { assert(internalKeyStorageToken == null); internalKeyStorageToken = token; } } assert(internalKeyStorageToken != null); assert(internalCryptoToken != null); } /** * The internal cryptographic services token. */ private CryptoToken internalCryptoToken; /** * The internal key storage token. */ private CryptoToken internalKeyStorageToken; /** * Native code to traverse all PKCS #11 modules, wrap each one in * a PK11Module, and insert each PK11Module into the given vector. */ private native void putModulesInVector(Vector vector); /////////////////////////////////////////////////////////////////////// // Constructor and Accessors /////////////////////////////////////////////////////////////////////// /** * Constructor, for internal use only. */ protected CryptoManager() { TokenSupplierManager.setTokenSupplier(this); reloadModules(); } public static boolean isInitialized() { synchronized (CryptoManager.class) { return instance != null; } } /** * Retrieve the single instance of CryptoManager. * This cannot be called before initialization. * * @see #initialize(InitializationValues) * @exception NotInitializedException If * initialize(InitializationValues has not yet been * called. * @return CryptoManager instance. */ public static CryptoManager getInstance() throws NotInitializedException { synchronized (CryptoManager.class) { if (instance != null) { return instance; } } /* Java has lazy-loading Security providers; until a provider * is requested, it won't be loaded. This means we could've * initialized the CryptoManager via the JSSLoader but we won't * know about it until it is explicitly requested. * * This breaks tests looking to configure a file-based password * handler: if the very first call is to getInstance(...) instead * of a Provider call, we'd fail. * * Try to get the Mozilla-JSS provider by name before reporting * that we're not initialized. * * However, in order for the JSSProvider to load, we need to * release our lock on CryptoManager (and in particular, on * CryptoManager.instance). * * For a more complete discussion see docs/usage/cryptomanager.md * in the source distribution. */ java.security.Provider p = Security.getProvider("Mozilla-JSS"); synchronized (CryptoManager.class) { // When instance is properly configured, use that. if (instance != null) { return instance; } // Otherwise, work around this by looking at what JSSProvider // created. Note that this will work when CryptoManager no // longer is a singleton and becomes tied to a specific // JSSProvider instance. if (p instanceof JSSProvider) { JSSProvider jssProvider = (JSSProvider) p; assert jssProvider.getCryptoManager() != null; if (instance == null) { instance = jssProvider.getCryptoManager(); } return instance; } } throw new NotInitializedException(); } /** * The singleton instance, and a static initializer to create it. */ private static CryptoManager instance=null; /////////////////////////////////////////////////////////////////////// // FIPS management /////////////////////////////////////////////////////////////////////// /** * Enables or disables FIPS-140-2 compliant mode. If this returns true, * you must reloadModules(). This should only be called once in a program, * at the beginning, because it invalidates tokens and modules. * * @param fips true to turn FIPS compliant mode on, false to turn it off. */ private static native boolean enableFIPS(boolean fips) throws GeneralSecurityException; /** * Determines whether FIPS-140-2 compliance is active. * * @return true if the security library is in FIPS-140-2 compliant mode. */ public synchronized native boolean FIPSEnabled(); /////////////////////////////////////////////////////////////////////// // Password Callback management /////////////////////////////////////////////////////////////////////// /** * This function sets the global password callback. It is * not thread-safe to change this. *

The callback may be NULL, in which case password callbacks will * fail gracefully. * * @param pwcb Password callback. */ public synchronized void setPasswordCallback(PasswordCallback pwcb) { passwordCallback = pwcb; setNativePasswordCallback( pwcb ); } private native void setNativePasswordCallback(PasswordCallback cb); /** * Returns the currently registered password callback. * * @return Password callback. */ public synchronized PasswordCallback getPasswordCallback() { return passwordCallback; } private PasswordCallback passwordCallback; //////////////////////////////////////////////////// // Initialization //////////////////////////////////////////////////// /** * Initialize the security subsystem. Opens the databases, loads all * PKCS #11 modules, initializes the internal random number generator. * The initialize methods that take arguments should be * called only once, otherwise they will throw * an exception. It is OK to call them after calling * initialize(). * * @param configDir The directory containing the security databases. * @exception org.mozilla.jss.KeyDatabaseException Unable to open * the key database, or it was currupted. * @exception org.mozilla.jss.CertDatabaseException Unable * to open the certificate database, or it was currupted. * @exception AlreadyInitializedException If the security subsystem is already initialized. * @exception GeneralSecurityException If other security error occurred. **/ public static synchronized void initialize( String configDir ) throws KeyDatabaseException, CertDatabaseException, AlreadyInitializedException, GeneralSecurityException { initialize( new InitializationValues(configDir) ); } /** * Initialize the security subsystem. Opens the databases, loads all * PKCS #11 modules, initializes the internal random number generator. * The initialize methods that take arguments should be * called only once, otherwise they will throw * an exception. It is OK to call them after calling * initialize(). * * @param values The options with which to initialize CryptoManager. * @exception org.mozilla.jss.KeyDatabaseException Unable to open * the key database, or it was corrupted. * @exception org.mozilla.jss.CertDatabaseException Unable * to open the certificate database, or it was currupted. * @exception AlreadyInitializedException If security subsystem is already initialized. * @exception GeneralSecurityException If other security error occurred. **/ public static synchronized void initialize( InitializationValues values ) throws KeyDatabaseException, CertDatabaseException, AlreadyInitializedException, GeneralSecurityException { if(instance != null) { throw new AlreadyInitializedException(); } if (values.ocspResponderURL != null) { if (values.ocspResponderCertNickname == null) { throw new GeneralSecurityException( "Must set ocspResponderCertNickname"); } } initializeAllNative2(values.configDir, values.certPrefix, values.keyPrefix, values.secmodName, values.readOnly, values.getManufacturerID(), values.getLibraryDescription(), values.getInternalTokenDescription(), values.getInternalKeyStorageTokenDescription(), values.getInternalSlotDescription(), values.getInternalKeyStorageSlotDescription(), values.getFIPSSlotDescription(), values.getFIPSKeyStorageSlotDescription(), values.ocspCheckingEnabled, values.ocspResponderURL, values.ocspResponderCertNickname, values.initializeJavaOnly, values.PKIXVerify, values.noCertDB, values.noModDB, values.forceOpen, values.noRootInit, values.optimizeSpace, values.PK11ThreadSafe, values.PK11Reload, values.noPK11Finalize, values.cooperate ); instance = new CryptoManager(); instance.setPasswordCallback(values.passwordCallback); if( values.fipsMode != InitializationValues.FIPSMode.UNCHANGED) { if( enableFIPS(values.fipsMode == InitializationValues.FIPSMode.ENABLED) ) { instance.reloadModules(); } } // Force class load before we install the provider. Otherwise we get // an infinite loop as the Security manager tries to instantiate the // digest to verify its own JAR file. JSSMessageDigestSpi mds = new JSSMessageDigestSpi.SHA1(); logger.debug("Loaded " + mds); // Force the KeyType class to load before we can install JSS as a // provider. JSS's signature provider accesses KeyType. KeyType kt = KeyType.getKeyTypeFromAlgorithm( SignatureAlgorithm.RSASignatureWithSHA1Digest); logger.debug("Loaded " + kt); if( values.installJSSProvider ) { int insert_position = 1; if (!values.installJSSProviderFirst) { insert_position = java.security.Security.getProviders().length + 1; } int position = java.security.Security.insertProviderAt(new JSSProvider(true), insert_position); if (position < 0) { logger.warn("JSS provider is already installed"); } // This returns -1 if the provider was already installed, in which // case it is not installed again. Is this // an error? I don't think so, although it might be confusing // if the provider is not in the position they expected. // However, this will only happen if they are installing the // provider themselves, so presumably they know what they're // doing. } if( values.removeSunProvider ) { java.security.Security.removeProvider("SUN"); } logger.info("JSS CryptoManager: successfully initialized from NSS database at " + values.configDir); } private static native void initializeAllNative2(String configDir, String certPrefix, String keyPrefix, String secmodName, boolean readOnly, String manufacturerID, String libraryDescription, String internalTokenDescription, String internalKeyStorageTokenDescription, String internalSlotDescription, String internalKeyStorageSlotDescription, String fipsSlotDescription, String fipsKeyStorageSlotDescription, boolean ocspCheckingEnabled, String ocspResponderURL, String ocspResponderCertNickname, boolean initializeJavaOnly, boolean PKIXVerify, boolean noCertDB, boolean noModDB, boolean forceOpen, boolean noRootInit, boolean optimizeSpace, boolean PK11ThreadSafe, boolean PK11Reload, boolean noPK11Finalize, boolean cooperate) throws KeyDatabaseException, CertDatabaseException, AlreadyInitializedException; ///////////////////////////////////////////////////////////// // Cert Lookup ///////////////////////////////////////////////////////////// /** * Retrieves all CA certificates in the trust database. This * is a fairly expensive operation in that it involves traversing * the entire certificate database. * @return An array of all CA certificates stored permanently * in the trust database. */ public native X509Certificate[] getCACerts(); /** * Retrieves all certificates in the trust database. This * is a fairly expensive operation in that it involves traversing * the entire certificate database. * @return An array of all certificates stored permanently * in the trust database. */ public native X509Certificate[] getPermCerts(); /** * Imports a chain of certificates. The leaf certificate may be a * a user certificate, that is, a certificate that belongs to the * current user and whose private key is available for use. * If the leaf certificate is a user certificate, it is stored * on the token * that contains the corresponding private key, and is assigned the * given nickname. * * @param certPackage An encoded certificate or certificate chain. * Acceptable * encodings are binary PKCS #7 SignedData objects and * DER-encoded certificates, which may or may not be wrapped * in a Base-64 encoding package surrounded by * "-----BEGIN CERTIFICATE-----" and * "-----END CERTIFICATE-----". * @param nickname The nickname for the user certificate. It must * be unique. It is ignored if there is no user certificate. * @return The leaf certificate from the chain. * @exception CertificateEncodingException If the package encoding * was not recognized. * @exception NicknameConflictException If the leaf certificate * is a user certificate, and another certificate already has the * given nickname. * @exception UserCertConflictException If the leaf certificate * is a user certificate, but it has already been imported. * @exception NoSuchItemOnTokenException If the leaf certificate is * a user certificate, but the matching private key cannot be found. * @exception TokenException If an error occurs importing a leaf * certificate into a token. */ public X509Certificate importCertPackage(byte[] certPackage, String nickname ) throws CertificateEncodingException, NicknameConflictException, UserCertConflictException, NoSuchItemOnTokenException, TokenException { return importCertPackageNative(certPackage, nickname, false, false); } /** * Imports a chain of certificates. The leaf of the chain is a CA * certificate AND a user certificate (this would only be called by * a CA installing its own certificate). * * @param certPackage An encoded certificate or certificate chain. * Acceptable * encodings are binary PKCS #7 SignedData objects and * DER-encoded certificates, which may or may not be wrapped * in a Base-64 encoding package surrounded by * "-----BEGIN CERTIFICATE-----" and * "-----END CERTIFICATE-----". * @param nickname The nickname for the user certificate. It must * be unique. * @return The leaf certificate from the chain. * @exception CertificateEncodingException If the package encoding * was not recognized. * @exception NicknameConflictException If the leaf certificate * another certificate already has the given nickname. * @exception UserCertConflictException If the leaf certificate * has already been imported. * @exception NoSuchItemOnTokenException If the the private key matching * the leaf certificate cannot be found. * @exception TokenException If an error occurs importing the leaf * certificate into a token. */ public X509Certificate importUserCACertPackage(byte[] certPackage, String nickname) throws CertificateEncodingException, NicknameConflictException, UserCertConflictException, NoSuchItemOnTokenException, TokenException { return importCertPackageNative(certPackage, nickname, false, true); } /** * Imports a chain of certificates, none of which is a user certificate. * * @param certPackage An encoded certificate or certificate chain. * Acceptable * encodings are binary PKCS #7 SignedData objects and * DER-encoded certificates, which may or may not be wrapped * in a Base-64 encoding package surrounded by * "-----BEGIN CERTIFICATE-----" and * "-----END CERTIFICATE-----". * @return The leaf certificate from the chain. * @exception CertificateEncodingException If the package encoding * was not recognized. * @exception TokenException If an error occurs importing a leaf * certificate into a token. */ public X509Certificate importCACertPackage(byte[] certPackage) throws CertificateEncodingException, TokenException { try { return importCertPackageNative(certPackage, null, true, false); } catch(NicknameConflictException e) { logger.error("importing CA certs caused nickname conflict", e); throw new RuntimeException("Importing CA certs caused nickname conflict: " + e.getMessage(), e); } catch(UserCertConflictException e) { logger.error("importing CA certs caused user cert conflict", e); throw new RuntimeException("Importing CA certs caused user cert conflict: " + e.getMessage(), e); } catch(NoSuchItemOnTokenException e) { logger.error("importing CA certs caused NoSuchItemOnTokenException", e); throw new RuntimeException("Importing CA certs caused NoSuchItemOnToken"+ "Exception: " + e.getMessage(), e); } } /** * Imports a single certificate into the permanent certificate * database. * * @param cert the certificate you want to add * @param nickname the nickname you want to refer to the certificate as * (must not be null) * @return Certificate object. * @throws TokenException If an error occurred in the token. * @throws InvalidNicknameException If the nickname is invalid. */ public InternalCertificate importCertToPerm(X509Certificate cert, String nickname) throws TokenException, InvalidNicknameException { if (nickname==null) { throw new InvalidNicknameException("Nickname must be non-null"); } else { return importCertToPermNative(cert,nickname); } } /** * Imports a single DER-encoded certificate into the permanent or temporary * certificate database. */ public X509Certificate importDERCert(byte[] cert, CertificateUsage usage, boolean permanent, String nickname) { return importDERCertNative(cert, usage.getEnumValue(), permanent, nickname); } private native X509Certificate importDERCertNative(byte[] cert, int usage, boolean permanent, String nickname); private native InternalCertificate importCertToPermNative(X509Certificate cert, String nickname) throws TokenException; /** * @param noUser true if we know that none of the certs are user certs. * In this case, no attempt will be made to find a matching private * key for the leaf certificate. */ private native X509Certificate importCertPackageNative(byte[] certPackage, String nickname, boolean noUser, boolean leafIsCA) throws CertificateEncodingException, NicknameConflictException, UserCertConflictException, NoSuchItemOnTokenException, TokenException; /*============ CRL importing stuff ********************************/ private static int TYPE_KRL = 0; private static int TYPE_CRL = 1; /** * Imports a CRL, and stores it into the cert7.db * Validate CRL then import it to the dbase. If there is already a CRL with the * same CA in the dbase, it will be replaced if derCRL is more up to date. * * @param crl the DER-encoded CRL. * @param url the URL where this CRL can be retrieved from (for future updates). * [ note that CRLs are not retrieved automatically ]. Can be null * @exception CRLImportException If the package encoding * was not recognized. * @exception TokenException If an error occurred in the token. */ public void importCRL(byte[] crl,String url) throws CRLImportException, TokenException { importCRLNative(crl,url,TYPE_CRL); } /** * Imports a CRL, and stores it into the cert7.db * * @param the DER-encoded CRL. */ private native void importCRLNative(byte[] crl, String url, int rl_type) throws CRLImportException, TokenException; /*============ Cert Exporting stuff ********************************/ /** * Exports one or more certificates into a PKCS #7 certificate container. * This is just a SignedData object whose certificates * field contains the given certificates but whose content field * is empty. * * @param certs One or more certificates that should be exported into * the PKCS #7 object. The leaf certificate should be the first * in the chain. The output of buildCertificateChain * would be appropriate here. * @exception CertificateEncodingException If the array is empty, * or an error occurred encoding the certificates. * @return A byte array containing a PKCS #7 SignedData object. * @see #buildCertificateChain */ public native byte[] exportCertsToPKCS7(X509Certificate[] certs) throws CertificateEncodingException; /** * Looks up a certificate given its nickname. * * @param nickname The nickname of the certificate to look for. * @return The certificate matching this nickname, if one is found. * @exception ObjectNotFoundException If no certificate could be found * with the given nickname. * @exception TokenException If an error occurs in the security library. */ public org.mozilla.jss.crypto.X509Certificate findCertByNickname(String nickname) throws ObjectNotFoundException, TokenException { assert(nickname!=null); return findCertByNicknameNative(nickname); } /** * Returns all certificates with the given nickname. * * @param nickname The nickname of the certificate to look for. * @return The certificates matching this nickname. The array may be empty * if no matching certs were found. * @exception TokenException If an error occurs in the security library. */ public org.mozilla.jss.crypto.X509Certificate[] findCertsByNickname(String nickname) throws TokenException { assert(nickname!=null); return findCertsByNicknameNative(nickname); } /** * Looks up a certificate by issuer and serial number. The internal * database and all PKCS #11 modules are searched. * * @param derIssuer The DER encoding of the certificate issuer name. * The issuer name has ASN.1 type Name, which is defined in * X.501. * @param serialNumber The certificate serial number. * @return Certificate object. * @exception ObjectNotFoundException If the certificate is not found * in the internal certificate database or on any PKCS #11 token. * @exception TokenException If an error occurs in the security library. */ public org.mozilla.jss.crypto.X509Certificate findCertByIssuerAndSerialNumber(byte[] derIssuer, INTEGER serialNumber) throws ObjectNotFoundException, TokenException { try { ANY sn = (ANY) ASN1Util.decode(ANY.getTemplate(), ASN1Util.encode(serialNumber) ); return findCertByIssuerAndSerialNumberNative(derIssuer, sn.getContents() ); } catch( InvalidBERException e ) { throw new RuntimeException("Invalid BER encoding of INTEGER: " + e.getMessage(), e); } } /** * @param serialNumber The contents octets of a DER-encoding of the * certificate serial number. */ private native org.mozilla.jss.crypto.X509Certificate findCertByIssuerAndSerialNumberNative(byte[] derIssuer, byte[] serialNumber) throws ObjectNotFoundException, TokenException; protected native org.mozilla.jss.crypto.X509Certificate findCertByNicknameNative(String nickname) throws ObjectNotFoundException, TokenException; protected native org.mozilla.jss.crypto.X509Certificate[] findCertsByNicknameNative(String nickname) throws TokenException; ///////////////////////////////////////////////////////////// // build cert chains ///////////////////////////////////////////////////////////// /** * Given a certificate, constructs its certificate chain. It may * or may not chain up to a trusted root. * @param leaf The certificate that is the starting point of the chain. * @return An array of certificates, starting at the leaf and ending * with the highest certificate on the chain that was found. * @throws CertificateException If the certificate is not recognized * by the underlying provider. * @throws TokenException If an error occurred in the token. */ public org.mozilla.jss.crypto.X509Certificate[] buildCertificateChain(org.mozilla.jss.crypto.X509Certificate leaf) throws java.security.cert.CertificateException, TokenException { if( ! (leaf instanceof PK11Cert) ) { throw new CertificateException( "Certificate is not a PKCS #11 certificate"); } return buildCertificateChainNative((PK11Cert)leaf); } native org.mozilla.jss.crypto.X509Certificate[] buildCertificateChainNative(PK11Cert leaf) throws CertificateException, TokenException; ///////////////////////////////////////////////////////////// // lookup private keys ///////////////////////////////////////////////////////////// /** * Looks up the PrivateKey matching the given certificate. * * @param cert Certificate. * @return Private key. * @exception ObjectNotFoundException If no private key can be * found matching the given certificate. * @exception TokenException If an error occurs in the security library. */ public org.mozilla.jss.crypto.PrivateKey findPrivKeyByCert(org.mozilla.jss.crypto.X509Certificate cert) throws ObjectNotFoundException, TokenException { assert(cert!=null); if(! (cert instanceof org.mozilla.jss.pkcs11.PK11Cert)) { throw new ObjectNotFoundException("Non-pkcs11 cert passed to PK11Finder"); } return findPrivKeyByCertNative(cert); } protected native org.mozilla.jss.crypto.PrivateKey findPrivKeyByCertNative(org.mozilla.jss.crypto.X509Certificate cert) throws ObjectNotFoundException, TokenException; ///////////////////////////////////////////////////////////// // Provide Pseudo-Random Number Generation ///////////////////////////////////////////////////////////// /** * Retrieves a FIPS-140-2 validated random number generator. * * @return A JSS SecureRandom implemented with FIPS-validated NSS. */ public org.mozilla.jss.crypto.JSSSecureRandom createPseudoRandomNumberGenerator() { return new PK11SecureRandom(); } /** * Retrieves a FIPS-140-2 validated random number generator. * * @return A JSS SecureRandom implemented with FIPS-validated NSS. */ @Override public org.mozilla.jss.crypto.JSSSecureRandom getSecureRNG() { return new PK11SecureRandom(); } /********************************************************************/ /* The VERSION Strings should be updated everytime a new release */ /* of JSS is generated. Note that this is done by changing */ /* cmake/JSSConfig.cmake. */ /********************************************************************/ public native static int getJSSMajorVersion(); public native static int getJSSMinorVersion(); public native static int getJSSPatchVersion(); private native static boolean getJSSDebug(); public static final String JAR_JSS_VERSION = "JSS_VERSION = JSS_" + getJSSMajorVersion() + "_" + getJSSMinorVersion() + "_" + getJSSPatchVersion(); public static final boolean JSS_DEBUG = getJSSDebug(); // Hashtable is synchronized. private Hashtable perThreadTokenTable = new Hashtable<>(); /** * Sets the default token for the current thread. This token will * be used when JSS is called through the JCA interface, which has * no means of specifying which token to use. * *

If no token is set, the InternalKeyStorageToken will be used. Setting * this thread's token to null will also cause the * InternalKeyStorageToken to be used. * * @param token The token to use for crypto operations. Specifying * null will cause the InternalKeyStorageToken to be used. */ @Override public void setThreadToken(CryptoToken token) { if( token != null ) { perThreadTokenTable.put(Thread.currentThread(), token); } else { perThreadTokenTable.remove(Thread.currentThread()); } } /** * Returns the default token for the current thread. This token will * be used when JSS is called through the JCA interface, which has * no means of specifying which token to use. * *

If no token is set, the InternalKeyStorageToken will be used. Setting * this thread's token to null will also cause the * InternalKeyStorageToken to be used. * * @return The default token for this thread. If it has not been specified, * it will be the InternalKeyStorageToken. */ @Override public CryptoToken getThreadToken() { CryptoToken tok = perThreadTokenTable.get(Thread.currentThread()); if( tok == null ) { tok = getInternalKeyStorageToken(); } return tok; } ///////////////////////////////////////////////////////////// // isCertValid ///////////////////////////////////////////////////////////// /** * Verify a certificate that exists in the given cert database, * check if is valid and that we trust the issuer. Verify time * against Now. * @param nickname The nickname of the certificate to verify. * @param checkSig verify the signature of the certificate * @return currCertificateUsage which contains current usage bit map as defined in CertificateUsage * * @exception InvalidNicknameException If the nickname is null * @exception ObjectNotFoundException If no certificate could be found * with the given nickname. */ public int isCertValid(String nickname, boolean checkSig) throws ObjectNotFoundException, InvalidNicknameException { if (nickname==null) { throw new InvalidNicknameException("Nickname must be non-null"); } int currCertificateUsage = 0x0000; // initialize it to 0 currCertificateUsage = verifyCertificateNowCUNative(nickname, checkSig); return currCertificateUsage; } private native int verifyCertificateNowCUNative(String nickname, boolean checkSig) throws ObjectNotFoundException; ///////////////////////////////////////////////////////////// // isCertValid ///////////////////////////////////////////////////////////// /** * Verify a certificate that exists in the given cert database, * check if is valid and that we trust the issuer. Verify time * against Now. * @param nickname The nickname of the certificate to verify. * @param checkSig verify the signature of the certificate * @param certificateUsage see certificateUsage defined to verify Certificate; to retrieve current certificate usage, call the isCertValid() above * @return true for success; false otherwise * * @exception InvalidNicknameException If the nickname is null * @exception ObjectNotFoundException If no certificate could be found * with the given nickname. * @deprecated Use verifyCertificate() instead */ @Deprecated public boolean isCertValid(String nickname, boolean checkSig, CertificateUsage certificateUsage) throws ObjectNotFoundException, InvalidNicknameException { if (nickname==null) { throw new InvalidNicknameException("Nickname must be non-null"); } // 0 certificate usage will get current usage // should call isCertValid() call above that returns certificate usage if ((certificateUsage == null) || (certificateUsage == CertificateUsage.CheckAllUsages)){ int currCertificateUsage = 0x0000; currCertificateUsage = verifyCertificateNowCUNative(nickname, checkSig); if (currCertificateUsage == CertificateUsage.basicCertificateUsages){ // cert is good for nothing return false; } else return true; } else { return verifyCertificateNowNative(nickname, checkSig, certificateUsage.getUsage()); } } /** * Verify a certificate that exists in the given cert database, * check if it's valid and that we trust the issuer. Verify time * against now. * @param nickname nickname of the certificate to verify. * @param checkSig verify the signature of the certificate * @param certificateUsage see certificate usage defined to verify certificate * * @exception InvalidNicknameException If the nickname is null. * @exception ObjectNotFoundException If no certificate could be found * with the given nickname. * @exception CertificateException If certificate is invalid. */ public void verifyCertificate(String nickname, boolean checkSig, CertificateUsage certificateUsage) throws ObjectNotFoundException, InvalidNicknameException, CertificateException { int usage = certificateUsage == null ? 0 : certificateUsage.getUsage(); verifyCertificateNowNative2(nickname, checkSig, usage); } /** * Verify an X509Certificate by checking if it's valid and that we trust * the issuer. Verify time against now. * @param cert the certificate to verify * @param checkSig verify the signature of the certificate * @param certificateUsage see certificate usage defined to verify certificate * * @exception InvalidNicknameException If the nickname is null. * @exception ObjectNotFoundException If no certificate could be found * with the given nickname. * @exception CertificateException If certificate is invalid. */ public void verifyCertificate(X509Certificate cert, boolean checkSig, CertificateUsage certificateUsage) throws ObjectNotFoundException, InvalidNicknameException, CertificateException { int usage = certificateUsage == null ? 0 : certificateUsage.getUsage(); verifyCertificateNowNative3(cert, checkSig, usage); } private native boolean verifyCertificateNowNative(String nickname, boolean checkSig, int certificateUsage) throws ObjectNotFoundException; private native void verifyCertificateNowNative2( String nickname, boolean checkSig, int certificateUsage) throws ObjectNotFoundException, InvalidNicknameException, CertificateException; private native void verifyCertificateNowNative3( X509Certificate cert, boolean checkSig, int certificateUsage) throws ObjectNotFoundException, InvalidNicknameException, CertificateException; /** * note: this method calls obsolete function in NSS * * Verify a certificate that exists in the given cert database, * check if is valid and that we trust the issuer. Verify time * against Now. * @param nickname The nickname of the certificate to verify. * @param checkSig verify the signature of the certificate * @param certUsage see exposed certUsage defines to verify Certificate * @return true for success; false otherwise * * @exception InvalidNicknameException If the nickname is null * @exception ObjectNotFoundException If no certificate could be found * with the given nickname. */ public boolean isCertValid(String nickname, boolean checkSig, CertUsage certUsage) throws ObjectNotFoundException, InvalidNicknameException { if (nickname==null) { throw new InvalidNicknameException("Nickname must be non-null"); } return verifyCertNowNative(nickname, checkSig, certUsage.getUsage()); } /* * Obsolete in NSS */ private native boolean verifyCertNowNative(String nickname, boolean checkSig, int cUsage) throws ObjectNotFoundException; ///////////////////////////////////////////////////////////// // isCertValid ///////////////////////////////////////////////////////////// /** * Verify a certificate in memory. Check if * valid and that we trust the issuer. Verify time * against Now. * @param certPackage certificate in memory * @param checkSig verify the signature of the certificate * @param certUsage see exposed certUsage defines to verify Certificate * @return true for success; false otherwise * * @exception TokenException unable to insert temporary certificate * into database. * @exception CertificateEncodingException If the package encoding * was not recognized. */ public boolean isCertValid(byte[] certPackage, boolean checkSig, CertUsage certUsage) throws TokenException, CertificateEncodingException { return verifyCertTempNative(certPackage , checkSig, certUsage.getUsage()); } private native boolean verifyCertTempNative(byte[] certPackage, boolean checkSig, int cUsage) throws TokenException, CertificateEncodingException; /////////////////////////////////////////////////////////////////////// // OCSP management /////////////////////////////////////////////////////////////////////// /* OCSP Policy related */ public enum OCSPPolicy { NONE, NORMAL, LEAF_AND_CHAIN; } private static OCSPPolicy ocspPolicy = OCSPPolicy.NONE; /** * Gets the current ocsp Policy. * Currently we only support 2 modes OCSP_LEAF_AND_CHAIN_POLICY. * And OCSP_NORMAL_POLICY, which is current processing , by default. * If we have AIA based OCSP enabled we will check all certs in the chain. * using PKIX cert verfication calls in the various cert auth callbacks we * have. * @return - The current ocsp policy in effect. */ public static synchronized int getOCSPPolicy() { return ocspPolicy.ordinal(); } /** * Gets the current OCSP Policy. * * @see getOCSPPolicy() * * @return - The current OCSP policy in effect. */ public static synchronized OCSPPolicy getOCSPPolicyEnum() { return ocspPolicy; } /** * Sets the current ocsp Policy. * Currently we only support one mode OCSP_LEAF_AND_CHAIN_POLICY. * If we have AIA based OCSP enabled we will check all certs in the chain. * using PKIX cert verfication calls in the various cert auth callbacks we * have. * @param policy - Either cert and chain or normal default processing. * */ public static synchronized void setOCSPPolicy(OCSPPolicy policy) { ocspPolicy = policy; } /** * Enables OCSP, note when you Initialize JSS for the first time, for * backwards compatibility, the initialize will enable OCSP if you * previously set values.ocspCheckingEnabled and * values.ocspResponderURL/values.ocspResponderCertNickname * configureOCSP will allow changing of the the OCSPResponder at runtime. * @param ocspCheckingEnabled true or false to enable/disable OCSP * @param ocspResponderURL - url of the OCSP responder * @param ocspResponderCertNickname - the nickname of the OCSP * signer certificate or the CA certificate found in the cert DB * @throws GeneralSecurityException If a security error has occurred. */ public void configureOCSP( boolean ocspCheckingEnabled, String ocspResponderURL, String ocspResponderCertNickname ) throws GeneralSecurityException { /* set the ocsp policy */ if(ocspCheckingEnabled && ocspResponderURL == null && ocspResponderCertNickname == null) { setOCSPPolicy(OCSPPolicy.LEAF_AND_CHAIN); } else { setOCSPPolicy(OCSPPolicy.NORMAL); } configureOCSPNative(ocspCheckingEnabled, ocspResponderURL, ocspResponderCertNickname ); } private native void configureOCSPNative( boolean ocspCheckingEnabled, String ocspResponderURL, String ocspResponderCertNickname ) throws GeneralSecurityException; /** * change OCSP cache settings * @param ocsp_cache_size max cache entries * @param ocsp_min_cache_entry_duration minimum seconds to next fetch attempt * @param ocsp_max_cache_entry_duration maximum seconds to next fetch attempt * @throws GeneralSecurityException If a security error has occurred. */ public void OCSPCacheSettings( int ocsp_cache_size, int ocsp_min_cache_entry_duration, int ocsp_max_cache_entry_duration) throws GeneralSecurityException { OCSPCacheSettingsNative(ocsp_cache_size, ocsp_min_cache_entry_duration, ocsp_max_cache_entry_duration); } private native void OCSPCacheSettingsNative( int ocsp_cache_size, int ocsp_min_cache_entry_duration, int ocsp_max_cache_entry_duration) throws GeneralSecurityException; /** * set OCSP timeout value * @param ocsp_timeout OCSP timeout in seconds * @throws GeneralSecurityException If a security error has occurred. */ public void setOCSPTimeout( int ocsp_timeout ) throws GeneralSecurityException { setOCSPTimeoutNative( ocsp_timeout); } private native void setOCSPTimeoutNative( int ocsp_timeout ) throws GeneralSecurityException; /** * Shutdowns this CryptoManager instance and the associated NSS * initialization. */ public synchronized void shutdown() throws Exception { try { NativeProxy.purgeAllInRegistry(); } finally { shutdownNative(); CryptoManager.instance = null; } } public native void shutdownNative(); } jss-5.0.0/src/main/java/org/mozilla/jss/DatabaseCloser.java000066400000000000000000000030241412550063600235240ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss; /** * A class for closing databases. Since closing the databases is * very dangerous and breaks the JSS model, it may only be done from * special applications. This class should be subclasses by * authorized subclasses. It cannot be instantiated itself. */ public abstract class DatabaseCloser { private static final String authorizedClosers[] = { "org.mozilla.certsetup.apps.CertSetup$DatabaseCloser", "org.mozilla.jss.CloseDBs" }; /** * Creates a new DatabaseCloser. This should only be called * from an authorized subclass. This class cannot itself be * instantiated. * * @throws Exception If the instantiation is not a valid subclass. */ public DatabaseCloser() throws Exception { Class clazz = this.getClass(); String name = clazz.getName(); boolean approved = false; for(int i=0; i < authorizedClosers.length; i++) { if( name.equals( authorizedClosers[i] ) ) { approved = true; break; } } if(!approved) { throw new Exception(); } } /** * Closes the certificate and key databases. This is extremely * dangerous. */ protected native void closeDatabases(); } jss-5.0.0/src/main/java/org/mozilla/jss/InitializationValues.java000066400000000000000000000461041412550063600250250ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss; import org.mozilla.jss.util.ConsolePasswordCallback; import org.mozilla.jss.util.PasswordCallback; /** * The various options that can be used to initialize CryptoManager. */ public final class InitializationValues { protected InitializationValues() { throw new RuntimeException("Default InitializationValues constructor"); } ///////////////////////////////////////////////////////////// // Constants ///////////////////////////////////////////////////////////// /** * Token names must be this length exactly. */ public final int TOKEN_LENGTH = 33; /** * Slot names must be this length exactly. */ public final int SLOT_LENGTH = 65; /** * ManufacturerID must be this length exactly. */ public final int MANUFACTURER_LENGTH = 33; /** * Library description must be this length exactly. */ public final int LIBRARY_LENGTH = 33; /** * This class enumerates the possible modes for FIPS compliance. */ public static final class FIPSMode { private FIPSMode() {} /** * Enable FIPS mode. */ public static final InitializationValues.FIPSMode ENABLED = new FIPSMode(); /** * Disable FIPS mode. */ public static final InitializationValues.FIPSMode DISABLED = new FIPSMode(); /** * Leave FIPS mode unchanged. All servers except Admin * Server should use this, because only Admin Server should * be altering FIPS mode. */ public static final InitializationValues.FIPSMode UNCHANGED = new FIPSMode(); } /** * Default constructor taking only the path to the NSS DB directory. */ public InitializationValues(String configDir) { this.configDir = configDir; } /** * Optional constructor taking the path to the NSS DB directory, * the prefix of the cert database, the prefix of the key database, * and the name of the secmod/pkcs11 database. */ public InitializationValues(String configDir, String certPrefix, String keyPrefix, String secmodName) { this.configDir = configDir; this.certPrefix = certPrefix; this.keyPrefix = keyPrefix; this.secmodName = secmodName; } public String configDir = null; public String certPrefix = null; public String keyPrefix = null; public String secmodName = null; /** * The password callback to be used by JSS whenever a password * is needed. May be NULL, in which the library will immediately fail * to get a password if it tries to login automatically while * performing * a cryptographic operation. It will still work if the token * has been manually logged in with CryptoToken.login. *

The default is a ConsolePasswordCallback. */ public PasswordCallback passwordCallback = new ConsolePasswordCallback(); /** * The FIPS mode of the security library. Servers should * use FIPSMode.UNCHANGED, since only * Admin Server is supposed to alter this value. *

The default is FIPSMode.UNCHANGED. */ public InitializationValues.FIPSMode fipsMode = FIPSMode.UNCHANGED; /** * To open the databases in read-only mode, set this flag to * true. The default is false, meaning * the databases are opened in read-write mode. */ public boolean readOnly = false; //////////////////////////////////////////////////////////////////// // Manufacturer ID //////////////////////////////////////////////////////////////////// /** * Returns the Manufacturer ID of the internal PKCS #11 module. *

The default is "mozilla.org ". * * @return Manufacturer ID. */ public String getManufacturerID() { return manufacturerID; } /** * Sets the Manufacturer ID of the internal PKCS #11 module. * This value must be exactly MANUFACTURER_LENGTH * characters long. * * @param s Manufacturer ID. * @exception InvalidLengthException If s.length() is not * exactly MANUFACTURER_LENGTH. */ public void setManufacturerID(String s) throws InvalidLengthException { if (s.length() != MANUFACTURER_LENGTH) { String msg = "Expected internal manufacturer ID description "; msg += "of length " + MANUFACTURER_LENGTH + " but was "; msg += s.length(); throw new InvalidLengthException(); } manufacturerID = s; } private String manufacturerID = "mozilla.org "; //////////////////////////////////////////////////////////////////// // Library Description //////////////////////////////////////////////////////////////////// /** * Returns the description of the internal PKCS #11 module. *

The default is "Internal Crypto Services ". * * @return Library description. */ public String getLibraryDescription() { return libraryDescription; } /** * Sets the description of the internal PKCS #11 module. * This value must be exactly LIBRARY_LENGTH * characters long. * * @param s Library description. * @exception InvalidLengthException If s.length() is * not exactly LIBRARY_LENGTH. */ public void setLibraryDescription(String s) throws InvalidLengthException { if (s.length() != LIBRARY_LENGTH) { String msg = "Expected internal library description of length "; msg += LIBRARY_LENGTH + " but was " + s.length(); throw new InvalidLengthException(msg); } libraryDescription = s; } private String libraryDescription = "Internal Crypto Services "; //////////////////////////////////////////////////////////////////// // Internal Token Description //////////////////////////////////////////////////////////////////// /** * Returns the description of the internal PKCS #11 token. *

The default is "Internal Crypto Services Token ". * * @return Description of internal PKCS #11 token. */ public String getInternalTokenDescription() { return internalTokenDescription; } /** * Sets the description of the internal PKCS #11 token. * This value must be exactly TOKEN_LENGTH characters long. * * @param s Description of internal PKCS #11 token. * @exception InvalidLengthException If s.length() is * not exactly TOKEN_LENGTH. */ public void setInternalTokenDescription(String s) throws InvalidLengthException { if (s.length() != TOKEN_LENGTH) { String msg = "Expected internal token description of length "; msg += TOKEN_LENGTH + " but was " + s.length(); throw new InvalidLengthException(msg); } internalTokenDescription = s; } private String internalTokenDescription = "NSS Generic Crypto Services "; //////////////////////////////////////////////////////////////////// // Internal Key Storage Token Description //////////////////////////////////////////////////////////////////// /** * Returns the description of the internal PKCS #11 key storage token. *

The default is "Internal Key Storage Token ". * * @return Description of internal PKCS #11 key storage token. */ public String getInternalKeyStorageTokenDescription() { return internalKeyStorageTokenDescription; } /** * Sets the description of the internal PKCS #11 key storage token. * This value must be exactly TOKEN_LENGTH characters long. * * @param s Description of internal PKCS #11 key storage token. * @exception InvalidLengthException If s.length() is * not exactly TOKEN_LENGTH. */ public void setInternalKeyStorageTokenDescription(String s) throws InvalidLengthException { if (s.length() != TOKEN_LENGTH) { String msg = "Expected internal key storage token description "; msg += "of length " + TOKEN_LENGTH + " but was " + s.length(); throw new InvalidLengthException(msg); } internalKeyStorageTokenDescription = s; } private String internalKeyStorageTokenDescription = "Internal Key Storage Token "; //////////////////////////////////////////////////////////////////// // Internal Slot Description //////////////////////////////////////////////////////////////////// /** * Returns the description of the internal PKCS #11 slot. *

The default is "NSS Internal Cryptographic Services ". * * @return Description of internal PKCS #11 slot. */ public String getInternalSlotDescription() { return internalSlotDescription; } /** * Sets the description of the internal PKCS #11 slot. * This value must be exactly SLOT_LENGTH characters * long. * * @param s Description of internal PKCS #11 slot. * @exception InvalidLengthException If s.length() is * not exactly SLOT_LENGTH. */ public void setInternalSlotDescription(String s) throws InvalidLengthException { if (s.length() != SLOT_LENGTH) { String msg = "Expected internal slot description of length "; msg += SLOT_LENGTH + " but was " + s.length(); throw new InvalidLengthException(msg); } internalSlotDescription = s; } private String internalSlotDescription = "NSS Internal Cryptographic Services "; //////////////////////////////////////////////////////////////////// // Internal Key Storage Slot Description //////////////////////////////////////////////////////////////////// /** * Returns the description of the internal PKCS #11 key storage slot. *

The default is "NSS Internal Private Key and Certificate Storage ". * * @return Description of internal PKCS #11 key storage slot. */ public String getInternalKeyStorageSlotDescription() { return internalKeyStorageSlotDescription; } /** * Sets the description of the internal PKCS #11 key storage slot. * This value must be exactly SLOT_LENGTH characters * long. * * @param s Description of internal PKCS #11 key storage slot. * @exception InvalidLengthException If s.length() is * not exactly SLOT_LENGTH. */ public void setInternalKeyStorageSlotDescription(String s) throws InvalidLengthException { if (s.length() != SLOT_LENGTH) { String msg = "Expected internal key storage slot description of "; msg += "length " + SLOT_LENGTH + " but was " + s.length(); throw new InvalidLengthException(msg); } internalKeyStorageSlotDescription = s; } private String internalKeyStorageSlotDescription = "NSS User Private Key and Certificate Services "; //////////////////////////////////////////////////////////////////// // FIPS Slot Description //////////////////////////////////////////////////////////////////// /** * Returns the description of the internal PKCS #11 FIPS slot. *

The default is * "NSS FIPS 140-2 User Private Key Services". * * @return Description of internal PKCS #11 FIPS slot. */ public String getFIPSSlotDescription() { return FIPSSlotDescription; } /** * Sets the description of the internal PKCS #11 FIPS slot. * This value must be exactly SLOT_LENGTH characters * long. * * @param s Description of internal PKCS #11 FIPS slot. * @exception InvalidLengthException If s.length() is * not exactly SLOT_LENGTH. */ public void setFIPSSlotDescription(String s) throws InvalidLengthException { if (s.length() != SLOT_LENGTH) { String msg = "Expected FIPS slot description of length "; msg += SLOT_LENGTH + " but was " + s.length(); throw new InvalidLengthException(msg); } FIPSSlotDescription = s; } private String FIPSSlotDescription = "NSS FIPS 140-2 User Private Key Services "; //////////////////////////////////////////////////////////////////// // FIPS Key Storage Slot Description //////////////////////////////////////////////////////////////////// /** * Returns the description of the internal PKCS #11 FIPS * Key Storage slot. *

The default is * "NSS FIPS 140-2 User Private Key Services". * * @return Description of internal PKCS #11 FIPS key storage slot. */ public String getFIPSKeyStorageSlotDescription() { return FIPSKeyStorageSlotDescription; } /** * Sets the description of the internal PKCS #11 FIPS Key Storage slot. * This value must be exactly SLOT_LENGTH characters * long. * * @param s Description of internal PKCS #11 FIPS key storage slot. * @exception InvalidLengthException If s.length() is * not exactly SLOT_LENGTH. */ public void setFIPSKeyStorageSlotDescription(String s) throws InvalidLengthException { if (s.length() != SLOT_LENGTH) { String msg = "Expected FIPS key storage slot description of "; msg += "length " + SLOT_LENGTH + " but was " + s.length(); throw new InvalidLengthException(msg); } FIPSKeyStorageSlotDescription = s; } private String FIPSKeyStorageSlotDescription = "NSS FIPS 140-2 User Private Key Services "; /** * To have NSS check the OCSP responder for when verifying * certificates, set this flags to true. It is false by * default. */ public boolean ocspCheckingEnabled = false; /** * Specify the location and cert of the responder. * If OCSP checking is enabled *and* this variable is * set to some URL, all OCSP checking will be done via * this URL. * * If this variable is null, the OCSP responder URL will * be obtained from the AIA extension in the certificate * being queried. * * If this is set, you must also set ocspResponderCertNickname * */ public String ocspResponderURL = null; /** * The nickname of the cert to trust (expected) to * sign the OCSP responses. * Only checked when the OCSPResponder value is set. */ public String ocspResponderCertNickname = null; /** * Install the JSS crypto provider. Default is true. */ public boolean installJSSProvider = true; /** * Remove the Sun crypto provider. Default is false. */ public boolean removeSunProvider = false; /** * Whether or not to initialize the JSS provider first. Default is true. */ public boolean installJSSProviderFirst = true; /** * If true, none of the underlying NSS components will * be initialized. Only the Java portions of JSS will be * initialized. This should only be used if NSS has been initialized * elsewhere. * *

Specifically, the following components will not be * configured by CryptoManager.initialize if this flag is set: *

    *
  • The NSS databases. *
  • OCSP checking. *
  • The NSS password callback. *
  • The internal PKCS #11 software token's identifier labels: * slot, token, module, and manufacturer. *
  • The minimum PIN length for the software token. *
  • The frequency with which the user must login to the software * token. *
  • The cipher strength policy (export/domestic). *
* *

The default is false. */ public boolean initializeJavaOnly = false; /** * Enable PKIX verify rather than the old cert library, * to verify certificates. Default is false. */ public boolean PKIXVerify = false; /** * Don't open the cert DB and key DB's, just * initialize the volatile certdb. Default is false. */ public boolean noCertDB = false; /** * Don't open the security module DB, * just initialize the PKCS #11 module. * Default is false. */ public boolean noModDB = false; /** * Continue to force initializations even if the * databases cannot be opened. * Default is false. */ public boolean forceOpen = false; /** * Don't try to look for the root certs module * automatically. * Default is false. */ public boolean noRootInit = false; /** * Use smaller tables and caches. * Default is false. */ public boolean optimizeSpace = false; /** * only load PKCS#11 modules that are * thread-safe, ie. that support locking - either OS * locking or NSS-provided locks . If a PKCS#11 * module isn't thread-safe, don't serialize its * calls; just don't load it instead. This is necessary * if another piece of code is using the same PKCS#11 * modules that NSS is accessing without going through * NSS, for example the Java SunPKCS11 provider. * Default is false. */ public boolean PK11ThreadSafe = false; /** * Init PK11Reload to ignore the CKR_CRYPTOKI_ALREADY_INITIALIZED * error when loading PKCS#11 modules. This is necessary * if another piece of code is using the same PKCS#11 * modules that NSS is accessing without going through * NSS, for example Java SunPKCS11 provider. * Default is false. */ public boolean PK11Reload = false; /** * never call C_Finalize on any * PKCS#11 module. This may be necessary in order to * ensure continuous operation and proper shutdown * sequence if another piece of code is using the same * PKCS#11 modules that NSS is accessing without going * through NSS, for example Java SunPKCS11 provider. * The following limitation applies when this is set : * SECMOD_WaitForAnyTokenEvent will not use * C_WaitForSlotEvent, in order to prevent the need for * C_Finalize. This call will be emulated instead. * Default is false. */ public boolean noPK11Finalize = false; /** * Sets 4 recommended options for applications that * use both NSS and the Java SunPKCS11 provider. * Default is false. */ public boolean cooperate = false; } jss-5.0.0/src/main/java/org/mozilla/jss/InvalidLengthException.java000066400000000000000000000013701412550063600252610ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss; public final class InvalidLengthException extends Exception { private static final long serialVersionUID = 1L; public InvalidLengthException() {} public InvalidLengthException(String mesg) { super(mesg); } public InvalidLengthException(String mesg, Throwable cause) { super(mesg, cause); } public InvalidLengthException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(mesg, cause, enableSuppression, writableStackTrace); } } jss-5.0.0/src/main/java/org/mozilla/jss/JSSLoader.java000066400000000000000000000337601412550063600224500ustar00rootroot00000000000000package org.mozilla.jss; import java.io.FileInputStream; import java.io.InputStream; import java.util.Properties; import org.mozilla.jss.util.Password; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * The JSS Loader facilitates loading JSS via the Provider interface directly, * including from a static java.security configuration file. * * This replaces the previous CryptoManager.initialize(...) approach, allowing * better control over where the JSSProvider gets loaded. In order to use this * provider, the caller has to specify a configuration file (either via a * String path or its contents via an InputStream). This configuration file is * a java.util.Properties file. The following keys are understood: * * - nss.config_dir -- the path to the NSS DB to initialize with * - nss.cert_prefix -- the prefix for the certificate store * - nss.key_prefix -- the prefix for the key store * - nss.secmod_name -- the name of the secmod file * * - nss.read_only -- whether to open the NSS DB read-only (default: false) * - nss.java_only -- whether to initialize only the java portion of JSS, * and assume that NSS is already initialized (default: * false) * * - nss.pkix_verify -- whether to use PKIX for verification (default: false) * - nss.no_cert_db -- whether to open the certificate and key databases; * see InitializationValues for more info (default: false) * - nss.no_mod_db -- whether to open the security module database; see * InitializationValues for more info (default: false) * - nss.force_open -- whether to force initializations even if the database * cannot be opened; see InitializationValues for more * info (default: false) * - nss.no_root_init -- whether to look for root certificate module and load * it; see InitializationValues for more info * (default: false) * - nss.optimize_space -- whether to use smaller tables and caches; see * InitializationValues for more info (default: false) * - nss.pk11_thread_safe -- whether to only load PKCS#11 modules that are * thread-safe; see InitializationValues for more * info (default: false) * - nss.pk11_reload -- whether to ignore already initialized errors when * loading PKCS#11 modules; see InitializationValues for * more info (default: false) * - nss.no_pk11_finalize -- whether to avoid calling C_Finalize on PKCS#11 * modules; see InitializationValues for more info * (default: false) * - nss.cooperate -- whether to cooperate with other parts of the program * already having initialized NSS (default: false) * * - jss.experimental.sslengine -- whether to enable experimental SSLEngine * support * * - jss.fips -- whether to switch this NSS DB into FIPS mode; allowed values * are ENABLED (to force FIPS mode), DISABLED (to force * non-FIPS mode), or UNCHANGED (default, to infer the value * from the NSS DB and/or the system) * * - jss.ocsp.enabled -- whether or not to enable OCSP checking * - jss.ocsp.responder.url -- URL of the OCSP responder to check * - jss.ocsp.responder.cert_nickname -- nickname of the OCSP responder's * certificate in the NSS DB * - jss.ocsp.policy -- which JSS OCSP checking policy to use; allowed values * are NONE, NORMAL, and LEAF_AND_CHAIN; refer to * CryptoManager documentation for the difference * * - jss.password -- static password to use to authenticate to tokens; if * this fails, the user will be prompted via the console */ public class JSSLoader { public static Logger logger = LoggerFactory.getLogger(JSSLoader.class); /** * Initialize JSS from the specified path to a configuration file. */ public static CryptoManager init(String config_path) throws Exception { if (config_path == null) { String msg = "Please specify the path to the JSS configuration "; msg += "file in the java.security provider list."; throw new NullPointerException(msg); } try (FileInputStream fistream = new FileInputStream(config_path)) { return init(fistream); } } /** * Initialize JSS from an InputStream. */ public static CryptoManager init(InputStream istream) throws Exception { if (CryptoManager.isInitialized()) { return CryptoManager.getInstance(); } if (istream == null) { String msg = "Please specify the JSS configuration InputStream "; msg += "in order to properly install this provider."; throw new NullPointerException(msg); } Properties config = new Properties(); config.load(istream); InitializationValues ivs = constructIV(config); parseFipsMode(config, ivs); parseReadOnly(config, ivs); parseOCSPSettings(config, ivs); parseProviderSettings(config, ivs); parseNSSSettings(config, ivs); // For more information about the interactions between JSSLoader and // CryptoManager, see docs/usage/cryptomanager.md in the source // distribution. CryptoManager.initialize(ivs); CryptoManager cm = CryptoManager.getInstance(); parseOCSPPolicy(config, cm); parsePasswords(config, cm); parseExperimental(config); return cm; } /** * Constructs an InitializationValues from the specified properties files, * reading only the properties required to construct a new instance. * * These properties are: * - nss.config_dir * - nss.cert_prefix * - nss.key_prefix * - nss.secmod_name */ private static InitializationValues constructIV(Properties config) { String configDir = config.getProperty("nss.config_dir", "/etc/pki/nssdb"); String certPrefix = config.getProperty("nss.cert_prefix"); String keyPrefix = config.getProperty("nss.key_prefix"); String secmodName = config.getProperty("nss.secmod_name"); if (certPrefix == null && keyPrefix == null && secmodName == null) { return new InitializationValues(configDir); } return new InitializationValues(configDir, certPrefix, keyPrefix, secmodName); } /** * Updates the specified InitializationValues with the FIPS-specific * properties. * * These properties are: * - jss.fips */ private static void parseFipsMode(Properties config, InitializationValues ivs) { String mode = config.getProperty("jss.fips", "unchanged"); if (mode.equalsIgnoreCase("enabled")) { ivs.fipsMode = InitializationValues.FIPSMode.ENABLED; } else if (mode.equalsIgnoreCase("disabled")) { ivs.fipsMode = InitializationValues.FIPSMode.DISABLED; } else if (mode.equalsIgnoreCase("unchanged")) { ivs.fipsMode = InitializationValues.FIPSMode.UNCHANGED; } else { String msg = "Unknown value for jss.fips: " + mode + ". "; msg += "Expecting one of ENABLED, DISABLED, or UNCHANGED."; throw new RuntimeException(msg); } } /** * Update the specified InitializationValues with the value of the * nss.read_only property. */ private static void parseReadOnly(Properties config, InitializationValues ivs) { Boolean value = parseBoolean(config, "nss.read_only"); if (value != null) { ivs.readOnly = value; } } /** * Update the specified InitializationValues with the value of the OCSP * properties. * * These properties are: * - jss.ocsp.enabled * - jss.ocsp.responder.url * - jss.ocsp.responder.cert_nickname */ private static void parseOCSPSettings(Properties config, InitializationValues ivs) { Boolean enabled = parseBoolean(config, "jss.ocsp.enabled"); if (enabled != null) { ivs.ocspCheckingEnabled = enabled; } String url = config.getProperty("jss.ocsp.responder.url"); ivs.ocspResponderURL = url; String nickname = config.getProperty("jss.ocsp.responder.cert_nickname"); ivs.ocspResponderCertNickname = nickname; } /** * Configure the specified InitializationValues with the correct * provider-related properties. */ private static void parseProviderSettings(Properties config, InitializationValues ivs) { // We don't want to do any of this: if the user wanted to, they'd have // already specified this as part of the java.security configuration // file. Plus, we're installing ourselves as the Mozilla-JSS provider. ivs.installJSSProvider = false; ivs.removeSunProvider = false; ivs.installJSSProviderFirst = false; } /** * Configure the specified InitializationValues with the values of various * NSS-specific configuration values. * * These properties are: * - nss.java_only * - nss.pkix_verify * - nss.no_cert_db * - nss.no_mod_db * - nss.force_open * - nss.no_root_init * - nss.optimize_space * - nss.pk11_thread_safe * - nss.pk11_reload * - nss.no_pk11_finalize * - nss.cooperate */ private static void parseNSSSettings(Properties config, InitializationValues ivs) { Boolean initializeJavaOnly = parseBoolean(config, "nss.java_only"); if (initializeJavaOnly != null) { ivs.initializeJavaOnly = initializeJavaOnly; } Boolean PKIXVerify = parseBoolean(config, "nss.pkix_verify"); if (PKIXVerify!= null) { ivs.PKIXVerify= PKIXVerify; } Boolean noCertDB = parseBoolean(config, "nss.no_cert_db"); if (noCertDB != null) { ivs.noCertDB = noCertDB; } Boolean noModDB = parseBoolean(config, "nss.no_mod_db"); if (noModDB != null) { ivs.noModDB = noModDB; } Boolean forceOpen = parseBoolean(config, "nss.force_open"); if (forceOpen != null) { ivs.forceOpen = forceOpen; } Boolean noRootInit = parseBoolean(config, "nss.no_root_init"); if (noRootInit != null) { ivs.noRootInit = noRootInit; } Boolean optimizeSpace = parseBoolean(config, "nss.optimize_space"); if (optimizeSpace != null) { ivs.optimizeSpace = optimizeSpace; } Boolean PK11ThreadSafe = parseBoolean(config, "nss.pk11_thread_safe"); if (PK11ThreadSafe != null) { ivs.PK11ThreadSafe = PK11ThreadSafe; } Boolean PK11Reload = parseBoolean(config, "nss.pk11_reload"); if (PK11Reload != null) { ivs.PK11Reload = PK11Reload; } Boolean noPK11Finalize = parseBoolean(config, "nss.no_pk11_finalize"); if (noPK11Finalize != null) { ivs.noPK11Finalize = noPK11Finalize; } Boolean cooperate = parseBoolean(config, "nss.cooperate"); if (cooperate != null) { ivs.cooperate = cooperate; } } /** * Once the CryptoManager has been initialized, update it with the value * of the remaining OCSP propertiy, jss.ocsp.policy. */ private static void parseOCSPPolicy(Properties config, CryptoManager cm) { String policy = config.getProperty("jss.ocsp.policy", "NONE"); if (policy.equalsIgnoreCase("none")) { CryptoManager.setOCSPPolicy(CryptoManager.OCSPPolicy.NONE); } else if (policy.equalsIgnoreCase("normal")) { CryptoManager.setOCSPPolicy(CryptoManager.OCSPPolicy.NORMAL); } else if (policy.equalsIgnoreCase("leaf_and_chain")) { CryptoManager.setOCSPPolicy(CryptoManager.OCSPPolicy.LEAF_AND_CHAIN); } else { String msg = "Unknown value for jss.ocsp.policy: " + policy + "."; msg += "Expecting one of NONE, NORMAL, or LEAF_AND_CHAIN."; throw new RuntimeException(msg); } } /** * Once the CryptoManager has been initialized, update it with the correct * PasswordCallback handler. * * Currently only understands a hard-coded password set via jss.password. */ private static void parsePasswords(Properties config, CryptoManager cm) { String password = config.getProperty("jss.password"); if (password != null && !password.isEmpty()) { Password pass_cb = new Password(password.toCharArray()); cm.setPasswordCallback(pass_cb); } } /** * Check for exerpimental flags. */ private static void parseExperimental(Properties config) { Boolean sslengine = parseBoolean(config, "jss.experimental.sslengine"); if (sslengine != null) { JSSProvider.ENABLE_JSSENGINE = sslengine; } } /** * Helper function to parse a boolean value at the given key name. * * Returns true if the value is true or yes, false if the value is * false or no, and null if the value is empty or not present. Throws * an exception for a malformed value. Case insensitive. */ private static Boolean parseBoolean(Properties config, String key_name) { String value = config.getProperty(key_name); if (value == null || value.isEmpty()) { return null; } if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes")) { return true; } if (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("no")) { return false; } String msg = "Unknown value for boolean " + key_name + ": " + value; msg += ". Expecting true, false, or not specified."; throw new RuntimeException(msg); } } jss-5.0.0/src/main/java/org/mozilla/jss/JSSProvider.java000066400000000000000000000526701412550063600230350ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss; import java.io.InputStream; import java.security.Provider; public final class JSSProvider extends java.security.Provider { public static boolean ENABLE_JSSENGINE = true; private static final long serialVersionUID = 1L; /********************************************************************/ /* The VERSION Strings should be updated everytime a new release */ /* of JSS is generated. Note that this is done by changing */ /* cmake/JSSConfig.cmake. */ /********************************************************************/ private static int JSS_MAJOR_VERSION = CryptoManager.getJSSMajorVersion(); private static int JSS_MINOR_VERSION = CryptoManager.getJSSMinorVersion(); private static int JSS_PATCH_VERSION = CryptoManager.getJSSPatchVersion(); private static double JSS_VERSION = JSS_MAJOR_VERSION + (JSS_MINOR_VERSION * 100 + JSS_PATCH_VERSION)/10000.0; private static JSSLoader loader = new JSSLoader(); private static CryptoManager cm; public JSSProvider() { this(CryptoManager.isInitialized()); } public JSSProvider(boolean initialize) { super("Mozilla-JSS", JSS_VERSION, "Provides Signature, Message Digesting, and RNG"); if (initialize) { initializeProvider(); } } public JSSProvider(String config_path) throws Exception { this(false); configure(config_path); } public JSSProvider(InputStream config) throws Exception { this(false); cm = JSSLoader.init(config); initializeProvider(); } /** * Configure this instance of JSSProvider with the specified path * to a JSS configuration properties file. * * See JSSLoader's class description for a description of the JSS * configuration properties file and known values. * * If the JSSProvider is already loaded, this is a no-op. */ @Override public Provider configure(String arg) { try { cm = JSSLoader.init(arg); } catch (NullPointerException npe) { throw npe; } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } initializeProvider(); return this; } /** * Return the CryptoManager this instance was initialized with. */ public CryptoManager getCryptoManager() { if (cm == null) { try { cm = CryptoManager.getInstance(); } catch (NotInitializedException nie) {} } return cm; } protected void initializeProvider() { ///////////////////////////////////////////////////////////// // Signature ///////////////////////////////////////////////////////////// put("Signature.SHA1withDSA", "org.mozilla.jss.provider.java.security.JSSSignatureSpi$DSA"); put("Alg.Alias.Signature.DSA", "SHA1withDSA"); put("Alg.Alias.Signature.DSS", "SHA1withDSA"); put("Alg.Alias.Signature.SHA/DSA", "SHA1withDSA"); put("Alg.Alias.Signature.SHA-1/DSA", "SHA1withDSA"); put("Alg.Alias.Signature.SHA1/DSA", "SHA1withDSA"); put("Alg.Alias.Signature.DSAWithSHA1", "SHA1withDSA"); put("Alg.Alias.Signature.SHAwithDSA", "SHA1withDSA"); put("Signature.MD5/RSA", "org.mozilla.jss.provider.java.security.JSSSignatureSpi$MD5RSA"); put("Alg.Alias.Signature.MD5withRSA", "MD5/RSA"); put("Signature.MD2/RSA", "org.mozilla.jss.provider.java.security.JSSSignatureSpi$MD2RSA"); put("Signature.SHA-1/RSA", "org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA1RSA"); put("Alg.Alias.Signature.SHA1/RSA", "SHA-1/RSA"); put("Alg.Alias.Signature.SHA1withRSA", "SHA-1/RSA"); put("Signature.SHA-256/RSA", "org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA256RSA"); put("Alg.Alias.Signature.SHA256/RSA", "SHA-256/RSA"); put("Alg.Alias.Signature.SHA256withRSA", "SHA-256/RSA"); put("Signature.RSASSA-PSS", "org.mozilla.jss.provider.java.security.JSSSignatureSpi$RSAPSSSignature"); put("Alg.Alias.Signature.1.2.840.113549.1.1.10", "RSASSA-PSS"); put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.10", "RSASSA-PSS"); put("Signature.SHA-256/RSA/PSS", "org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA256RSAPSS"); put("Alg.Alias.Signature.SHA256withRSA/PSS","SHA-256/RSA/PSS"); put("Signature.SHA-384/RSA/PSS", "org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA384RSAPSS"); put("Alg.Alias.Signature.SHA384withRSA/PSS","SHA-384/RSA/PSS"); put("Signature.SHA-512/RSA/PSS", "org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA512RSAPSS"); put("Alg.Alias.Signature.SHA512withRSA/PSS","SHA-512/RSA/PSS"); put("Signature.SHA-384/RSA", "org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA384RSA"); put("Alg.Alias.Signature.SHA384/RSA", "SHA-384/RSA"); put("Alg.Alias.Signature.SHA384withRSA", "SHA-384/RSA"); put("Signature.SHA-512/RSA", "org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA512RSA"); put("Alg.Alias.Signature.SHA512/RSA", "SHA-512/RSA"); put("Alg.Alias.Signature.SHA512withRSA", "SHA-512/RSA"); // ECC put("Signature.SHA1withEC", "org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA1EC"); put("Alg.Alias.Signature.EC", "SHA1withEC"); put("Alg.Alias.Signature.ECC", "SHA1withEC"); put("Alg.Alias.Signature.ECDSA", "SHA1withEC"); put("Alg.Alias.Signature.SHA/EC", "SHA1withEC"); put("Alg.Alias.Signature.SHA1/EC", "SHA1withEC"); put("Alg.Alias.Signature.SHA-1/EC", "SHA1withEC"); put("Alg.Alias.Signature.SHA/ECDSA", "SHA1withEC"); put("Alg.Alias.Signature.SHA1/ECDSA", "SHA1withEC"); put("Alg.Alias.Signature.SHA1withECDSA", "SHA1withEC"); //JCE Standard Name put("Signature.SHA256withEC", "org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA256EC"); put("Alg.Alias.Signature.SHA256/EC", "SHA256withEC"); put("Alg.Alias.Signature.SHA-256/EC", "SHA256withEC"); put("Alg.Alias.Signature.SHA256withECDSA", "SHA256withEC"); //JCE Standard Name put("Signature.SHA384withEC", "org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA384EC"); put("Alg.Alias.Signature.SHA384/EC", "SHA384withEC"); put("Alg.Alias.Signature.SHA-384/EC", "SHA384withEC"); put("Alg.Alias.Signature.SHA384withECDSA", "SHA384withEC"); //JCE Standard Name put("Signature.SHA512withEC", "org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA512EC"); put("Alg.Alias.Signature.SHA512/EC", "SHA512withEC"); put("Alg.Alias.Signature.SHA-512/EC", "SHA512withEC"); put("Alg.Alias.Signature.SHA512withECDSA", "SHA512withEC"); //JCE Standard Name ///////////////////////////////////////////////////////////// // Message Digesting ///////////////////////////////////////////////////////////// put("MessageDigest.SHA-1", "org.mozilla.jss.provider.java.security.JSSMessageDigestSpi$SHA1"); put("MessageDigest.MD2", "org.mozilla.jss.provider.java.security.JSSMessageDigestSpi$MD2"); put("MessageDigest.MD5", "org.mozilla.jss.provider.java.security.JSSMessageDigestSpi$MD5"); put("MessageDigest.SHA-256", "org.mozilla.jss.provider.java.security.JSSMessageDigestSpi$SHA256"); put("MessageDigest.SHA-384", "org.mozilla.jss.provider.java.security.JSSMessageDigestSpi$SHA384"); put("MessageDigest.SHA-512", "org.mozilla.jss.provider.java.security.JSSMessageDigestSpi$SHA512"); put("Alg.Alias.MessageDigest.SHA1", "SHA-1"); put("Alg.Alias.MessageDigest.SHA", "SHA-1"); put("Alg.Alias.MessageDigest.SHA256", "SHA-256"); put("Alg.Alias.MessageDigest.SHA384", "SHA-384"); put("Alg.Alias.MessageDigest.SHA512", "SHA-512"); ///////////////////////////////////////////////////////////// // SecureRandom ///////////////////////////////////////////////////////////// put("SecureRandom.pkcs11prng", "org.mozilla.jss.provider.java.security.JSSSecureRandomSpi"); ///////////////////////////////////////////////////////////// // KeyPairGenerator ///////////////////////////////////////////////////////////// put("KeyPairGenerator.RSA", "org.mozilla.jss.provider.java.security.JSSKeyPairGeneratorSpi$RSA"); put("KeyPairGenerator.DSA", "org.mozilla.jss.provider.java.security.JSSKeyPairGeneratorSpi$DSA"); put("KeyPairGenerator.EC", "org.mozilla.jss.provider.java.security.JSSKeyPairGeneratorSpi$EC"); ///////////////////////////////////////////////////////////// // KeyFactory ///////////////////////////////////////////////////////////// put("KeyFactory.RSA", "org.mozilla.jss.provider.java.security.KeyFactorySpi1_2"); put("KeyFactory.DSA", "org.mozilla.jss.provider.java.security.KeyFactorySpi1_2"); put("KeyFactory.EC", "org.mozilla.jss.provider.java.security.KeyFactorySpi1_2"); ///////////////////////////////////////////////////////////// // KeyStore ///////////////////////////////////////////////////////////// put("KeyStore.PKCS11", "org.mozilla.jss.provider.java.security.JSSKeyStoreSpi"); ///////////////////////////////////////////////////////////// // AlgorithmParameters ///////////////////////////////////////////////////////////// put("AlgorithmParameters.IvAlgorithmParameters", "org.mozilla.jss.provider.java.security.IvAlgorithmParameters"); put("AlgorithmParameters.RC2AlgorithmParameters", "org.mozilla.jss.provider.java.security.RC2AlgorithmParameters"); put("AlgorithmParameters.RSAPSSAlgorithmParameters", "org.mozilla.jss.provider.java.security.RSAPSSAlgorithmParameters"); ///////////////////////////////////////////////////////////// // Cipher ///////////////////////////////////////////////////////////// put("Cipher.DES", "org.mozilla.jss.provider.javax.crypto.JSSCipherSpi$DES"); put("Cipher.DESede", "org.mozilla.jss.provider.javax.crypto.JSSCipherSpi$DESede"); put("Alg.Alias.Cipher.DES3", "DESede"); put("Cipher.AES", "org.mozilla.jss.provider.javax.crypto.JSSCipherSpi$AES"); put("Cipher.RC4", "org.mozilla.jss.provider.javax.crypto.JSSCipherSpi$RC4"); put("Cipher.RSA", "org.mozilla.jss.provider.javax.crypto.JSSCipherSpi$RSA"); put("Cipher.RC2", "org.mozilla.jss.provider.javax.crypto.JSSCipherSpi$RC2"); ///////////////////////////////////////////////////////////// // KeyGenerator ///////////////////////////////////////////////////////////// String kg_spi = "org.mozilla.jss.provider.javax.crypto.JSSKeyGeneratorSpi"; put("KeyGenerator.DES", kg_spi + "$DES"); put("KeyGenerator.DESede", kg_spi + "$DESede"); put("Alg.Alias.KeyGenerator.DES3", "DESede"); put("KeyGenerator.AES", kg_spi + "$AES"); put("KeyGenerator.RC4", kg_spi + "$RC4"); put("KeyGenerator.RC2", kg_spi + "$RC2"); put("KeyGenerator.HmacSHA1", kg_spi + "$HmacSHA1"); put("KeyGenerator.PBAHmacSHA1", kg_spi + "$PBAHmacSHA1"); put("KeyGenerator.HmacSHA256", kg_spi + "$HmacSHA256"); put("KeyGenerator.HmacSHA384", kg_spi + "$HmacSHA384"); put("KeyGenerator.HmacSHA512", kg_spi + "$HmacSHA512"); // KBKDF: Counter put("KeyGenerator.KbkdfCounter", kg_spi + "$KbkdfCounter"); put("Alg.Alias.KeyGenerator.KBKDF-Counter", "KbkdfCounter"); put("Alg.Alias.KeyGenerator.SP800-108-KDF-Counter", "KbkdfCounter"); put("Alg.Alias.KeyGenerator.SP800-108-Counter", "KbkdfCounter"); put("Alg.Alias.KeyGenerator.CounterKbkdf", "KbkdfCounter"); // KBKDF: Counter (data) put("KeyGenerator.KbkdfCounterData", kg_spi + "$KbkdfCounterData"); put("Alg.Alias.KeyGenerator.KBKDF-Counter-Data", "KbkdfCounterData"); put("Alg.Alias.KeyGenerator.SP800-108-KDF-Counter-Data", "KbkdfCounterData"); put("Alg.Alias.KeyGenerator.SP800-108-Counter-Data", "KbkdfCounterData"); put("Alg.Alias.KeyGenerator.CounterKbkdf-Data", "KbkdfCounterData"); // KBKDF: Feedback put("KeyGenerator.KbkdfFeedback", kg_spi + "$KbkdfFeedback"); put("Alg.Alias.KeyGenerator.KBKDF-Feedback", "KbkdfFeedback"); put("Alg.Alias.KeyGenerator.SP800-108-KDF-Feedback", "KbkdfFeedback"); put("Alg.Alias.KeyGenerator.SP800-108-Feedback", "KbkdfFeedback"); put("Alg.Alias.KeyGenerator.FeedbackKbkdf", "KbkdfFeedback"); // KBKDF: Feedback (data) put("KeyGenerator.KbkdfFeedbackData", kg_spi + "$KbkdfFeedbackData"); put("Alg.Alias.KeyGenerator.KBKDF-Feedback-Data", "KbkdfFeedbackData"); put("Alg.Alias.KeyGenerator.SP800-108-KDF-Feedback-Data", "KbkdfFeedbackData"); put("Alg.Alias.KeyGenerator.SP800-108-Feedback-Data", "KbkdfFeedbackData"); put("Alg.Alias.KeyGenerator.FeedbackKbkdf-Data", "KbkdfFeedbackData"); // KBKDF: Double Pipeline -- sometimes Pipeline KBKDF put("KeyGenerator.KbkdfDoublePipeline", kg_spi + "$KbkdfDoublePipeline"); put("Alg.Alias.KeyGenerator.KBKDF-DoublePipeline", "KbkdfDoublePipeline"); put("Alg.Alias.KeyGenerator.SP800-108-KDF-DoublePipeline", "KbkdfDoublePipeline"); put("Alg.Alias.KeyGenerator.SP800-108-DoublePipeline", "KbkdfDoublePipeline"); put("Alg.Alias.KeyGenerator.DoublePipelineKbkdf", "KbkdfDoublePipeline"); put("Alg.Alias.KeyGenerator.KbkdfPipeline", "KbkdfDoublePipeline"); put("Alg.Alias.KeyGenerator.KBKDF-Pipeline", "KbkdfDoublePipeline"); put("Alg.Alias.KeyGenerator.SP800-108-KDF-Pipeline", "KbkdfDoublePipeline"); put("Alg.Alias.KeyGenerator.SP800-108-Pipeline", "KbkdfDoublePipeline"); put("Alg.Alias.KeyGenerator.PipelineKbkdf", "KbkdfDoublePipeline"); // KBKDF: Double Pipeline (data) -- sometimes Pipeline KBKDF (data) put("KeyGenerator.KbkdfDoublePipelineData", kg_spi + "$KbkdfDoublePipelineData"); put("Alg.Alias.KeyGenerator.KBKDF-DoublePipeline-Data", "KbkdfDoublePipelineData"); put("Alg.Alias.KeyGenerator.SP800-108-KDF-DoublePipeline-Data", "KbkdfDoublePipelineData"); put("Alg.Alias.KeyGenerator.SP800-108-DoublePipeline-Data", "KbkdfDoublePipelineData"); put("Alg.Alias.KeyGenerator.DoublePipelineKbkdf-Data", "KbkdfDoublePipelineData"); put("Alg.Alias.KeyGenerator.KbkdfPipelineData", "KbkdfDoublePipelineData"); put("Alg.Alias.KeyGenerator.KBKDF-Pipeline-Data", "KbkdfDoublePipelineData"); put("Alg.Alias.KeyGenerator.SP800-108-KDF-Pipeline-Data", "KbkdfDoublePipelineData"); put("Alg.Alias.KeyGenerator.SP800-108-Pipeline-Data", "KbkdfDoublePipelineData"); put("Alg.Alias.KeyGenerator.PipelineKbkdf-Data", "KbkdfDoublePipelineData"); ///////////////////////////////////////////////////////////// // SecretKeyFactory ///////////////////////////////////////////////////////////// put("SecretKeyFactory.GenericSecret", "org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$GenericSecret"); put("Alg.Alias.SecretKeyFactory.GENERIC_SECRET", "GenericSecret"); put("SecretKeyFactory.DES", "org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$DES"); put("SecretKeyFactory.DESede", "org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$DESede"); put("Alg.Alias.SecretKeyFactory.DES3", "DESede"); put("SecretKeyFactory.AES", "org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$AES"); put("SecretKeyFactory.RC4", "org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$RC4"); put("SecretKeyFactory.RC2", "org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$RC2"); put("SecretKeyFactory.HmacSHA1", "org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$HmacSHA1"); put("SecretKeyFactory.PBAHmacSHA1", "org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$PBAHmacSHA1"); put("SecretKeyFactory.HmacSHA256", "org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$HmacSHA256"); put("SecretKeyFactory.HmacSHA384", "org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$HmacSHA384"); put("SecretKeyFactory.HmacSHA512", "org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$HmacSHA512"); put("SecretKeyFactory.PBEWithMD5AndDES", "org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$PBE_MD5_DES_CBC"); put("SecretKeyFactory.PBEWithSHA1AndDES", "org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$PBE_SHA1_DES_CBC"); put("SecretKeyFactory.PBEWithSHA1AndDESede", "org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$PBE_SHA1_DES3_CBC"); put("Alg.Alias.SecretKeyFactory.PBEWithSHA1AndDES3", "PBEWithSHA1AndDESede"); put("SecretKeyFactory.PBEWithSHA1And128RC4", "org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$PBE_SHA1_RC4_128"); ///////////////////////////////////////////////////////////// // MAC ///////////////////////////////////////////////////////////// put("Mac.HmacSHA1", "org.mozilla.jss.provider.javax.crypto.JSSMacSpi$HmacSHA1"); put("Alg.Alias.Mac.Hmac-SHA1", "HmacSHA1"); put("Mac.HmacSHA256", "org.mozilla.jss.provider.javax.crypto.JSSMacSpi$HmacSHA256"); put("Alg.Alias.Mac.Hmac-SHA256", "HmacSHA256"); put("Mac.HmacSHA384", "org.mozilla.jss.provider.javax.crypto.JSSMacSpi$HmacSHA384"); put("Alg.Alias.Mac.Hmac-SHA384", "HmacSHA384"); put("Mac.HmacSHA512", "org.mozilla.jss.provider.javax.crypto.JSSMacSpi$HmacSHA512"); put("Mac.CmacAES", "org.mozilla.jss.provider.javax.crypto.JSSMacSpi$CmacAES"); put("Alg.Alias.Mac.Hmac-SHA512", "HmacSHA512"); put("Alg.Alias.Mac.SHA-1-HMAC", "HmacSHA1"); put("Alg.Alias.Mac.SHA-256-HMAC", "HmacSHA256"); put("Alg.Alias.Mac.SHA-384-HMAC", "HmacSHA384"); put("Alg.Alias.Mac.SHA-512-HMAC", "HmacSHA512"); put("Alg.Alias.Mac.AES-128-CMAC", "CmacAES"); put("Alg.Alias.Mac.AES-192-CMAC", "CmacAES"); put("Alg.Alias.Mac.AES-256-CMAC", "CmacAES"); put("Alg.Alias.Mac.CmacAES128", "CmacAES"); put("Alg.Alias.Mac.CmacAES192", "CmacAES"); put("Alg.Alias.Mac.CmacAES256", "CmacAES"); put("Alg.Alias.Mac.AES_CMAC", "CmacAES"); put("Alg.Alias.Mac.CMAC_AES", "CmacAES"); ///////////////////////////////////////////////////////////// // KeyManagerFactory ///////////////////////////////////////////////////////////// put("KeyManagerFactory.NssX509", "org.mozilla.jss.provider.javax.crypto.JSSKeyManagerFactory"); put("Alg.Alias.KeyManagerFactory.SunX509", "NssX509"); put("Alg.Alias.KeyManagerFactory.PKIX", "SunX509"); ///////////////////////////////////////////////////////////// // TrustManagerFactory ///////////////////////////////////////////////////////////// put("TrustManagerFactory.NssX509", "org.mozilla.jss.provider.javax.crypto.JSSTrustManagerFactory"); put("Alg.Alias.TrustManagerFactory.SunX509", "NssX509"); put("Alg.Alias.TrustManagerFactory.PKIX", "NssX509"); put("Alg.Alias.TrustManagerFactory.X509", "NssX509"); put("Alg.Alias.TrustManagerFactory.X.509", "NssX509"); ///////////////////////////////////////////////////////////// // TLS ///////////////////////////////////////////////////////////// if (ENABLE_JSSENGINE) { put("SSLContext.Default", "org.mozilla.jss.provider.javax.net.JSSContextSpi"); put("SSLContext.SSL", "org.mozilla.jss.provider.javax.net.JSSContextSpi"); put("SSLContext.TLS", "org.mozilla.jss.provider.javax.net.JSSContextSpi"); put("SSLContext.TLSv1.1", "org.mozilla.jss.provider.javax.net.JSSContextSpi$TLSv11"); put("SSLContext.TLSv1.2", "org.mozilla.jss.provider.javax.net.JSSContextSpi$TLSv12"); put("SSLContext.TLSv1.3", "org.mozilla.jss.provider.javax.net.JSSContextSpi$TLSv13"); } } @Override public String toString() { String mozillaProviderVersion = JSS_MAJOR_VERSION + "." + JSS_MINOR_VERSION; if ( JSS_PATCH_VERSION != 0 ) { mozillaProviderVersion = mozillaProviderVersion + "." + JSS_PATCH_VERSION; } return "Mozilla-JSS version " + mozillaProviderVersion; } } jss-5.0.0/src/main/java/org/mozilla/jss/KeyDatabaseException.java000066400000000000000000000015461412550063600247130ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss; /** * This exception is thrown if the key database does not exist, or if * an error occurs while opening it. */ public class KeyDatabaseException extends java.lang.Exception { private static final long serialVersionUID = 1L; public KeyDatabaseException() {} public KeyDatabaseException(String mesg) { super(mesg); } public KeyDatabaseException(String mesg, Throwable cause) { super(mesg, cause); } public KeyDatabaseException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(mesg, cause, enableSuppression, writableStackTrace); } } jss-5.0.0/src/main/java/org/mozilla/jss/NicknameConflictException.java000066400000000000000000000005371412550063600257440ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss; public final class NicknameConflictException extends Exception { private static final long serialVersionUID = 1L; } jss-5.0.0/src/main/java/org/mozilla/jss/NoSuchTokenException.java000066400000000000000000000014401412550063600247270ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss; /** * Thrown if a token cannot be found. */ public class NoSuchTokenException extends java.lang.Exception { private static final long serialVersionUID = 1L; public NoSuchTokenException() {} public NoSuchTokenException(String mesg) { super(mesg); } public NoSuchTokenException(String mesg, Throwable cause) { super(mesg, cause); } public NoSuchTokenException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(mesg, cause, enableSuppression, writableStackTrace); } } jss-5.0.0/src/main/java/org/mozilla/jss/NotInitializedException.java000066400000000000000000000005351412550063600254610ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss; public final class NotInitializedException extends Exception { private static final long serialVersionUID = 1L; } jss-5.0.0/src/main/java/org/mozilla/jss/PK11Finder.c000066400000000000000000001676271412550063600220010ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "_jni/org_mozilla_jss_CryptoManager.h" #include #include #include #include #include #include #include #include #include #include #include #include "pk11util.h" #include "ssl/jssl.h" #include /* * This is a semi-private NSS function, exposed only for JSS. */ SECStatus CERT_ImportCAChainTrusted(SECItem *certs, int numcerts, SECCertUsage certUsage); /* * This is a private function, used only by JSS in this file. */ JNIEXPORT void JNICALL Java_org_mozilla_jss_CryptoManager_verifyCertificateNowNative2(JNIEnv *env, jobject self, jstring nickString, jboolean checkSig, jint required_certificateUsage); /* * This is a private function, used only by JSS in this file. */ JNIEXPORT void JNICALL Java_org_mozilla_jss_CryptoManager_verifyCertificateNowNative3(JNIEnv *env, jobject self, jstring nickString, jboolean checkSig, jint required_certificateUsage); /***************************************************************** * * CryptoManager. f i n d C e r t B y N i c k n a m e N a t i v e * */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_CryptoManager_findCertByNicknameNative (JNIEnv *env, jobject this, jstring nickname) { const char *nick = NULL; jobject certObject=NULL; CERTCertificate *cert=NULL; PK11SlotInfo *slot=NULL; PR_ASSERT(env!=NULL && this!=NULL && nickname!=NULL); nick = JSS_RefJString(env, nickname); PR_ASSERT(nick!=NULL); cert = JSS_PK11_findCertAndSlotFromNickname(nick, NULL, &slot); if(cert == NULL) { char *message = PR_smprintf("Certificate not found: %s", nick); JSS_throwMsg(env, OBJECT_NOT_FOUND_EXCEPTION, message); PR_smprintf_free(message); goto finish; } certObject = JSS_PK11_wrapCertAndSlot(env, &cert, &slot); finish: JSS_DerefJString(env, nickname, nick); if(cert != NULL) { CERT_DestroyCertificate(cert); } if(slot != NULL) { PK11_FreeSlot(slot); } return certObject; } /***************************************************************** * * CryptoManager. f i n d C e r t s B y N i c k n a m e N a t i v e * */ JNIEXPORT jobjectArray JNICALL Java_org_mozilla_jss_CryptoManager_findCertsByNicknameNative (JNIEnv *env, jobject this, jstring nickname) { CERTCertList *list =NULL; PK11SlotInfo *slot =NULL; jobjectArray certArray=NULL; CERTCertListNode *node; const char *nickChars=NULL; jclass certClass; int count; int i; /* convert the nickname string */ nickChars = JSS_RefJString(env, nickname); if( nickChars == NULL ) { goto finish; } /* get the list of certs with the given nickname */ list = JSS_PK11_findCertsAndSlotFromNickname( (char*)nickChars, NULL /*wincx*/, &slot); if( list == NULL ) { count = 0; } else { /* Since this structure changed in NSS_2_7_RTM (the reference */ /* to "count" was removed from the "list" structure) we must */ /* now count up the number of nodes manually! */ for( node = CERT_LIST_HEAD(list), count=0; ! CERT_LIST_END(node, list); node = CERT_LIST_NEXT(node), count++ ); } PR_ASSERT(count >= 0); /* create the cert array */ certClass = (*env)->FindClass(env, X509_CERT_CLASS); if( certClass == NULL ) { goto finish; } certArray = (*env)->NewObjectArray(env, count, certClass, NULL); if( certArray == NULL ) { /* exception was thrown */ goto finish; } if( list == NULL ) { goto finish; } /* traverse the list, placing each cert into the array */ for( node = CERT_LIST_HEAD(list), i=0; ! CERT_LIST_END(node, list); node = CERT_LIST_NEXT(node), i++ ) { CERTCertificate *cert; PK11SlotInfo *slotCopy; jobject certObj; /* Create a Java certificate object from the current CERTCertificate */ cert = CERT_DupCertificate(node->cert); slotCopy = PK11_ReferenceSlot(slot); certObj = JSS_PK11_wrapCertAndSlot(env, &cert, &slotCopy); if( certObj == NULL ) { goto finish; } /* put the Java certificate into the next element in the array */ (*env)->SetObjectArrayElement(env, certArray, i, certObj); if( (*env)->ExceptionOccurred(env) ) { goto finish; } } /* sanity check */ PR_ASSERT( i == count ); finish: if(list) { CERT_DestroyCertList(list); } if(slot) { PK11_FreeSlot(slot); } JSS_DerefJString(env, nickname, nickChars); return certArray; } /***************************************************************** * * CryptoManager.findCertByIssuerAndSerialNumberNative * */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_CryptoManager_findCertByIssuerAndSerialNumberNative (JNIEnv *env, jobject this, jbyteArray issuerBA, jbyteArray serialNumBA) { jobject certObject=NULL; CERTCertificate *cert=NULL; SECItem *issuer=NULL, *serialNum=NULL; CERTIssuerAndSN issuerAndSN; PK11SlotInfo *slot=NULL; PR_ASSERT(env!=NULL && this!=NULL); /* validate args */ if( issuerBA == NULL || serialNumBA == NULL ) { JSS_throwMsg(env, ILLEGAL_ARGUMENT_EXCEPTION, "NULL parameter passed to CryptoManager.findCertByIssuer" "AndSerialNumberNative"); goto finish; } /* convert byte arrays to SECItems */ issuer = JSS_ByteArrayToSECItem(env, issuerBA); if( issuer == NULL ) { goto finish; } serialNum = JSS_ByteArrayToSECItem(env, serialNumBA); if( serialNum == NULL ) { goto finish; } issuerAndSN.derIssuer = *issuer; issuerAndSN.serialNumber = *serialNum; /* lookup with PKCS #11 first, then use cert database */ cert = PK11_FindCertByIssuerAndSN(&slot, &issuerAndSN, NULL /*wincx*/); if( cert == NULL ) { JSS_nativeThrow(env, OBJECT_NOT_FOUND_EXCEPTION); goto finish; } certObject = JSS_PK11_wrapCertAndSlot(env, &cert, &slot); finish: if(slot) { PK11_FreeSlot(slot); } if(cert != NULL) { CERT_DestroyCertificate(cert); } if(issuer) { SECITEM_FreeItem(issuer, PR_TRUE /*freeit*/); } if(serialNum) { SECITEM_FreeItem(serialNum, PR_TRUE /*freeit*/); } return certObject; } /***************************************************************** * * CryptoManager. f i n d P r i v K e y B y C e r t N a t i v e * */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_CryptoManager_findPrivKeyByCertNative (JNIEnv *env, jobject this, jobject Cert) { PRThread * VARIABLE_MAY_NOT_BE_USED pThread=NULL; CERTCertificate *cert; PK11SlotInfo *slot; SECKEYPrivateKey *privKey=NULL; jobject Key = NULL; pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); PR_ASSERT( pThread != NULL); PR_ASSERT( env!=NULL && this!=NULL && Cert!=NULL); if( JSS_PK11_getCertPtr(env, Cert, &cert) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } if(cert==NULL) { PR_ASSERT(PR_FALSE); JSS_throw(env, OBJECT_NOT_FOUND_EXCEPTION); goto finish; } if( JSS_PK11_getCertSlotPtr(env, Cert, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } if(slot==NULL) { PR_ASSERT(PR_FALSE); JSS_throw(env, OBJECT_NOT_FOUND_EXCEPTION); goto finish; } privKey = PK11_FindPrivateKeyFromCert(slot, cert, NULL); if(privKey == NULL) { JSS_throw(env, OBJECT_NOT_FOUND_EXCEPTION); goto finish; } Key = JSS_PK11_wrapPrivKey(env, &privKey); finish: if(privKey != NULL) { SECKEY_DestroyPrivateKey(privKey); } PR_DetachThread(); return Key; } /*********************************************************************** * Node in linked list of certificates */ typedef struct JSScertNode { struct JSScertNode *next; CERTCertificate *cert; } JSScertNode; /*********************************************************************** * * c e r t _ c h a i n _ f r o m _ c e r t * * Builds a certificate chain from a certificate. Returns a Java array * of PK11Certs. * * INPUTS: * env * The JNI environment. Must not be NULL. * handle * The certificate database in which to search for the certificate * chain. This should usually be the default cert db. Must not * be NULL. * leaf * A CERTCertificate that is the leaf of the cert chain. Must not * be NULL. * RETURNS: * NULL if an exception was thrown, or * A Java array of PK11Cert objects which constitute the chain of * certificates. The chains starts with the one passed in and * continues until either a self-signed root is found or the next * certificate in the chain cannot be found. At least one cert will * be in the chain: the leaf certificate passed in. */ static jobjectArray cert_chain_from_cert(JNIEnv *env, CERTCertDBHandle *handle, CERTCertificate *leaf) { CERTCertificate *c; int i, len = 0; JSScertNode *head=NULL, *tail, *node; jobjectArray certArray = NULL; jclass certClass; PR_ASSERT(env!=NULL && handle!=NULL && leaf!=NULL); head = tail = (JSScertNode*) PR_CALLOC( sizeof(JSScertNode) ); if (head == NULL) goto no_memory; /* put primary cert first in the linked list */ head->cert = c = CERT_DupCertificate(leaf); head->next = NULL; PR_ASSERT(c != NULL); /* CERT_DupCertificate really can't return NULL */ len++; /* * add certs until we come to a self-signed one */ while(SECITEM_CompareItem(&c->derIssuer, &c->derSubject) != SECEqual) { c = CERT_FindCertByName(handle, &tail->cert->derIssuer); if (c == NULL) break; tail->next = (JSScertNode*) PR_CALLOC( sizeof(JSScertNode) ); tail = tail->next; if (tail == NULL) goto no_memory; tail->cert = c; len++; } /* * Turn the cert chain into a Java array of certificates */ certClass = (*env)->FindClass(env, CERT_CLASS_NAME); if(certClass==NULL) { ASSERT_OUTOFMEM(env); goto finish; } certArray = (*env)->NewObjectArray(env, len, certClass, (jobject)NULL); if(certArray==NULL) { ASSERT_OUTOFMEM(env); goto finish; } /* convert linked list to array, freeing the linked list as we go */ for( i=0; head != NULL; ++i ) { jobject certObj; node = head; PR_ASSERT(i < len); PR_ASSERT(node->cert != NULL); /* Convert C cert to Java cert */ certObj = JSS_PK11_wrapCert(env, &node->cert); PR_ASSERT( node->cert == NULL ); if(certObj == NULL) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL ); goto finish; } /* Insert Java cert into array */ (*env)->SetObjectArrayElement(env, certArray, i, certObj); if( (*env)->ExceptionOccurred(env) ) { goto finish; } /* Free this list element */ head = head->next; PR_Free(node); } goto finish; no_memory: JSS_throw(env, OUT_OF_MEMORY_ERROR); finish: /* Free the linked list of certs if it hasn't been deleted already */ while(head != NULL) { node = head; head = head->next; if (node->cert != NULL) { CERT_DestroyCertificate(node->cert); } PR_Free(node); } return certArray; } /***************************************************************** * * CryptoManager. b u i l d C e r t i f i c a t e C h a i n N a t i v e * * INPUTS: * env * The JNI environment. Must not be NULL. * this * The PK11Finder object. Must not be NULL. * leafCert * A PK11Cert object from which a cert chain will be built. * Must not be NULL. * RETURNS: * NULL if an exception occurred, or * An array of PK11Certs, the cert chain, with the leaf at the bottom. * There will always be at least one element in the array (the leaf). */ JNIEXPORT jobjectArray JNICALL Java_org_mozilla_jss_CryptoManager_buildCertificateChainNative (JNIEnv *env, jobject this, jobject leafCert) { PRThread * VARIABLE_MAY_NOT_BE_USED pThread=NULL; CERTCertificate *leaf; jobjectArray chainArray=NULL; CERTCertDBHandle *certdb; pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); PR_ASSERT(pThread != NULL); PR_ASSERT(env!=NULL && this!=NULL && leafCert!=NULL); if( JSS_PK11_getCertPtr(env, leafCert, &leaf) != PR_SUCCESS) { JSS_throwMsgPrErr(env, CERTIFICATE_EXCEPTION, "Could not extract pointer from PK11Cert"); goto finish; } PR_ASSERT(leaf!=NULL); certdb = CERT_GetDefaultCertDB(); if(certdb == NULL) { PR_ASSERT(PR_FALSE); JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "No default certificate database has been registered"); goto finish; } /* Get the cert chain */ chainArray = cert_chain_from_cert(env, certdb, leaf); if(chainArray == NULL) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } finish: PR_DetachThread(); return chainArray; } /*********************************************************************** * DERCertCollection */ typedef struct { SECItem *derCerts; int numCerts; } DERCertCollection; /*********************************************************************** * c o l l e c t _ c e r t s * * Copies certs into a new array. * * 'arg' is a pointer to a DERCertCollection structure, which will be filled in. * 'certs' is an array of pointers to SECItems. */ static SECStatus collect_der_certs(void *arg, SECItem **certs, int numcerts) { int itemsCopied=0; SECItem *certCopies; /* array of SECItem */ SECStatus rv; PR_ASSERT(arg!=NULL); certCopies = PR_MALLOC( sizeof(SECItem) * numcerts); ((DERCertCollection*)arg)->derCerts = certCopies; ((DERCertCollection*)arg)->numCerts = numcerts; if(certCopies == NULL) { return SECFailure; } for(itemsCopied=0; itemsCopied < numcerts; itemsCopied++) { rv=SECITEM_CopyItem(NULL, &certCopies[itemsCopied], certs[itemsCopied]); if( rv == SECFailure ) { goto finish; } } PR_ASSERT(itemsCopied == numcerts); return SECSuccess; finish: for(; itemsCopied >= 0; itemsCopied--) { SECITEM_FreeItem( &certCopies[itemsCopied], PR_FALSE /*freeit*/); } PR_Free( certCopies ); ((DERCertCollection*)arg)->derCerts = NULL; ((DERCertCollection*)arg)->numCerts = 0; return SECFailure; } /*********************************************************************** * CryptoManager.importCertToPerm * - add the certificate to the permanent database * * throws TOKEN_EXCEPTION */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_CryptoManager_importCertToPermNative (JNIEnv *env, jobject this, jobject cert, jstring nickString) { SECStatus rv; CERTCertificate *oldCert; jobject result=NULL; char *nickname=NULL; CERTCertificate **certArray = NULL; SECItem *derCertArray[1]; PK11SlotInfo *slot; /* first, get the NSS cert pointer from the 'cert' object */ if ( JSS_PK11_getCertPtr(env, cert, &oldCert) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } PR_ASSERT(oldCert != NULL); /* dereference, discarding const qualifier */ nickname = (char *)JSS_RefJString(env, nickString); /* Then, add to permanent database */ derCertArray[0] = &oldCert->derCert; rv = CERT_ImportCerts(CERT_GetDefaultCertDB(), -1 /* usage */, 1, derCertArray, &certArray, PR_TRUE /*keepCerts*/, PR_FALSE /*caOnly*/, nickname); if( rv != SECSuccess || certArray == NULL || certArray[0] == NULL) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Unable to insert certificate" " into permanent database"); goto finish; } slot = PK11_GetInternalKeySlot(); /* the permanent database token */ result = JSS_PK11_wrapCertAndSlot(env, &certArray[0], &slot); finish: /* this checks for NULL */ CERT_DestroyCertArray(certArray, 1); JSS_DerefJString(env, nickString, nickname); return result; } static unsigned char* data_start(unsigned char *buf, int length, unsigned int *data_length, PRBool includeTag) { unsigned char tag; int used_length= 0; tag = buf[used_length++]; /* blow out when we come to the end */ if (tag == 0) { return NULL; } *data_length = buf[used_length++]; if (*data_length&0x80) { int len_count = *data_length & 0x7f; *data_length = 0; while (len_count-- > 0 && used_length < length) { *data_length = (*data_length << 8) | buf[used_length++]; } } if (*data_length > (unsigned)(length-used_length) ) { *data_length = length-used_length; return NULL; } if (includeTag) *data_length += used_length; return (buf + (includeTag ? 0 : used_length)); } static PRStatus getCertFields(SECItem *derCert, SECItem *issuer, SECItem *serial, SECItem *subject) { unsigned char *buf; unsigned int buf_length; unsigned char *date; unsigned int datelen; unsigned char *cert = derCert->data; unsigned int cert_length = derCert->len; /* get past the signature wrap */ buf = data_start(cert,cert_length,&buf_length,PR_FALSE); if (buf == NULL) return PR_FAILURE; /* get into the raw cert data */ buf = data_start(buf,buf_length,&buf_length,PR_FALSE); if (buf == NULL) return PR_FAILURE; /* skip past any optional version number */ if ((buf[0] & 0xa0) == 0xa0) { date = data_start(buf,buf_length,&datelen,PR_FALSE); if (date == NULL) return PR_FAILURE; buf_length -= (date-buf) + datelen; buf = date + datelen; } /* serial number */ serial->data = data_start(buf,buf_length,&serial->len,PR_FALSE); if (serial->data == NULL) return PR_FAILURE; buf_length -= (serial->data-buf) + serial->len; buf = serial->data + serial->len; /* skip the OID */ date = data_start(buf,buf_length,&datelen,PR_FALSE); if (date == NULL) return PR_FAILURE; buf_length -= (date-buf) + datelen; buf = date + datelen; /* issuer */ issuer->data = data_start(buf,buf_length,&issuer->len,PR_TRUE); if (issuer->data == NULL) return PR_FAILURE; buf_length -= (issuer->data-buf) + issuer->len; buf = issuer->data + issuer->len; /* skip the date */ date = data_start(buf,buf_length,&datelen,PR_FALSE); if (date == NULL) return PR_FAILURE; buf_length -= (date-buf) + datelen; buf = date + datelen; /*subject */ subject->data=data_start(buf,buf_length,&subject->len,PR_TRUE); if (subject->data == NULL) return PR_FAILURE; buf_length -= (subject->data-buf) + subject->len; buf = subject->data +subject->len; /*subject */ return PR_SUCCESS; } /** * Returns * -1 if operation error. * 0 if no leaf found. * 1 if leaf is found */ static int find_child_cert( CERTCertDBHandle *certdb, SECItem *derCerts, int numCerts, int *linked, int cur_link, int *leaf_link ) { int i; int status = 0; SECItem parentIssuer, parentSerial, parentSubject; PRStatus decodeStatus; decodeStatus = getCertFields(&derCerts[cur_link], &parentIssuer, &parentSerial, &parentSubject); if( decodeStatus != PR_SUCCESS ) { status = -1; goto finish; } for (i=0; iExceptionOccurred(env)); goto finish; } /*************************************************** * Decode package with NSS function ***************************************************/ status = CERT_DecodeCertPackage((char*) packageBytes, (int) packageLen, collect_der_certs, (void*) &collection); if( status != SECSuccess || collection.numCerts < 1 ) { if( (*env)->ExceptionOccurred(env) == NULL) { JSS_throwMsgPrErr(env, CERTIFICATE_ENCODING_EXCEPTION, "Security library failed to decode certificate package"); } goto finish; } derCerts = collection.derCerts; numCerts = collection.numCerts; /*************************************************** * convert nickname to char*, discarding const ***************************************************/ nickChars = (char *)JSS_RefJString(env, nickString); /*************************************************** * user cert can be anywhere in the cert chain. loop and find it. * The point is to find the user cert with keys on the db, then * treat the other certs in the chain as CA certs to import. * The real order of the cert chain shouldn't matter, and shouldn't * be assumed, and the real location of this user cert in the chain, * if present, shouldn't be assumed either. ***************************************************/ if (numCerts > 1) { for (certi=0; certi= 1 ) { if (certi == 0) { status = CERT_ImportCAChainTrusted(derCerts+userCertFound, numCerts-userCertFound, certUsageUserCertImport); if(status != SECSuccess) { JSS_throwMsgPrErr(env, CERTIFICATE_ENCODING_EXCEPTION, "CERT_ImportCAChainTrusted returned an error"); goto finish; } } else if (certi == numCerts) { status = CERT_ImportCAChainTrusted(derCerts, numCerts-userCertFound, certUsageUserCertImport); if(status != SECSuccess) { JSS_throwMsgPrErr(env, CERTIFICATE_ENCODING_EXCEPTION, "CERT_ImportCAChainTrusted returned an error"); goto finish; } } else { status = CERT_ImportCAChainTrusted(derCerts, certi, certUsageUserCertImport); if(status != SECSuccess) { JSS_throwMsgPrErr(env, CERTIFICATE_ENCODING_EXCEPTION, "CERT_ImportCAChainTrusted returned an error"); goto finish; } status = CERT_ImportCAChainTrusted(derCerts+certi+1, numCerts-certi-1, certUsageUserCertImport); if(status != SECSuccess) { JSS_throwMsgPrErr(env, CERTIFICATE_ENCODING_EXCEPTION, "CERT_ImportCAChainTrusted returned an error"); goto finish; } } } /*************************************************** * Now lookup the leaf cert and make it into a Java object. ***************************************************/ if(slot) { PK11_FreeSlot(slot); } leafCert = PK11_FindCertByIssuerAndSN(&slot, &issuerAndSN, NULL); if( leafCert == NULL ) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to find certificate that was just imported"); goto finish; } leafObject = JSS_PK11_wrapCertAndSlot(env, &leafCert, &slot); finish: if(slot!=NULL) { PK11_FreeSlot(slot); } if(derCerts != NULL) { for(i=0; i < numCerts; i++) { SECITEM_FreeItem(&derCerts[i], PR_FALSE /*freeit*/); } PR_Free(derCerts); } /* don't copy back */ JSS_DerefByteArray(env, packageArray, packageBytes, JNI_ABORT); if(leafCert != NULL) { CERT_DestroyCertificate(leafCert); } JSS_DerefJString(env, nickString, nickChars); return leafObject; } /********************************************************************** * PKCS #7 Encoding data structures */ typedef struct BufferNodeStr { char *data; unsigned long len; struct BufferNodeStr *next; } BufferNode; typedef struct { BufferNode *head; BufferNode *tail; unsigned long totalLen; } EncoderCallbackInfo; /********************************************************************** * c r e a t e E n c o d e r C a l l b a c k I n f o * * Constructor for EncoderCallbackInfo structure. * Returns NULL if it runs out of memory, otherwise a new EncoderCallbackInfo. */ static EncoderCallbackInfo* createEncoderCallbackInfo() { EncoderCallbackInfo *info; info = PR_Malloc( sizeof(EncoderCallbackInfo) ); if( info == NULL ) { return NULL; } info->head = info->tail = NULL; info->totalLen = 0; return info; } /*********************************************************************** * d e s t r o y E n c o d e r C a l l b a c k I n f o * * Destructor for EncoderCallbackInfo structure. */ static void destroyEncoderCallbackInfo(EncoderCallbackInfo *info) { BufferNode *node; PR_ASSERT(info != NULL); while(info->head != NULL) { node = info->head; info->head = info->head->next; if(node->data) { PR_Free(node->data); } PR_Free(node); } PR_Free(info); } /*********************************************************************** * e n c o d e r O u t p u t C a l l b a c k * * Called by the PKCS #7 encoder whenever output is available. * Appends the output to a linked list. */ static void encoderOutputCallback( void *arg, const char *buf, unsigned long len) { BufferNode *node; EncoderCallbackInfo *info; /*************************************************** * validate arguments ***************************************************/ PR_ASSERT(arg!=NULL); info = (EncoderCallbackInfo*) arg; if(len == 0) { return; } PR_ASSERT(buf != NULL); /*************************************************** * Create a new node to store this information ***************************************************/ node = PR_NEW( BufferNode ); if( node == NULL ) { PR_ASSERT(PR_FALSE); goto finish; } node->len = len; node->data = PR_Malloc( len ); if( node->data == NULL ) { PR_ASSERT(PR_FALSE); goto finish; } memcpy( node->data, buf, len ); node->next = NULL; /*************************************************** * Stick the new node onto the end of the list ***************************************************/ if( info->head == NULL ) { PR_ASSERT(info->tail == NULL); info->head = info->tail = node; } else { PR_ASSERT(info->tail != NULL); info->tail->next = node; info->tail = node; } node = NULL; info->totalLen += len; finish: if(node != NULL) { if( node->data != NULL) { PR_Free(node->data); } PR_Free(node); } return; } /*********************************************************************** * CryptoManager.exportCertsToPKCS7 */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_CryptoManager_exportCertsToPKCS7 (JNIEnv *env, jobject this, jobjectArray certArray) { int i, certcount; SEC_PKCS7ContentInfo *cinfo=NULL; CERTCertificate *cert; jclass certClass; jbyteArray pkcs7ByteArray=NULL; jbyte *pkcs7Bytes=NULL; EncoderCallbackInfo *info=NULL; SECStatus status; /************************************************** * Validate arguments **************************************************/ PR_ASSERT(env!=NULL && this!=NULL); if(certArray == NULL) { JSS_throw(env, NULL_POINTER_EXCEPTION); goto finish; } certcount = (*env)->GetArrayLength(env, certArray); if(certcount < 1) { JSS_throwMsg(env, CERTIFICATE_ENCODING_EXCEPTION, "At least one certificate must be passed to exportCertsToPKCS7"); goto finish; } /* * JNI ID lookup */ certClass = (*env)->FindClass(env, CERT_CLASS_NAME); if(certClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } /*************************************************** * Add each cert to the PKCS #7 context. Create the context * for the first cert. ***************************************************/ for(i=0; i < certcount; i++) { jobject certObject; certObject = (*env)->GetObjectArrayElement(env, certArray, i); if( (*env)->ExceptionOccurred(env) != NULL) { goto finish; } PR_ASSERT( certObject != NULL ); /* * Make sure this is a PK11Cert */ if( ! (*env)->IsInstanceOf(env, certObject, certClass) ) { JSS_throwMsg(env, CERTIFICATE_ENCODING_EXCEPTION, "Certificate was not a PK11 Certificate"); goto finish; } /* * Convert it to a CERTCertificate */ if( JSS_PK11_getCertPtr(env, certObject, &cert) != PR_SUCCESS) { JSS_trace(env, JSS_TRACE_ERROR, "Unable to convert Java certificate to CERTCertificate"); goto finish; } PR_ASSERT(cert != NULL); if( i == 0 ) { /* * First certificate: create a new PKCS #7 cert-only context */ PR_ASSERT(cinfo == NULL); cinfo = SEC_PKCS7CreateCertsOnly(cert, PR_FALSE, /* don't include chain */ NULL /* cert db */ ); if(cinfo == NULL) { JSS_throwMsgPrErr(env, CERTIFICATE_ENCODING_EXCEPTION, "Failed to create PKCS #7 encoding context"); goto finish; } } else { /* * All remaining certificates: add cert to context */ PR_ASSERT(cinfo != NULL); if( SEC_PKCS7AddCertificate(cinfo, cert) != SECSuccess ) { JSS_throwMsgPrErr(env, CERTIFICATE_ENCODING_EXCEPTION, "Failed to add certificate to PKCS #7 encoding context"); goto finish; } } } PR_ASSERT( i == certcount ); PR_ASSERT( cinfo != NULL ); /************************************************** * Encode the PKCS #7 context into its DER encoding **************************************************/ info = createEncoderCallbackInfo(); if(info == NULL) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } status = SEC_PKCS7Encode(cinfo, encoderOutputCallback, (void*)info, NULL /* bulk key */, NULL /* password function */, NULL /* password function arg */ ); if( status != SECSuccess ) { JSS_throwMsgPrErr(env, CERTIFICATE_ENCODING_EXCEPTION, "Failed to encode PKCS #7 context"); } /* Make sure we got at least some data from the encoder */ PR_ASSERT(info->totalLen > 0); PR_ASSERT(info->head != NULL); /************************************************** * Create a new byte array to hold the encoded PKCS #7 **************************************************/ pkcs7ByteArray = (*env)->NewByteArray(env, info->totalLen); if(pkcs7ByteArray == NULL) { ASSERT_OUTOFMEM(env); goto finish; } pkcs7Bytes = (*env)->GetByteArrayElements(env, pkcs7ByteArray, NULL); if(pkcs7Bytes == NULL) { ASSERT_OUTOFMEM(env); goto finish; } /************************************************** * Copy the PKCS #7 encoding into the byte array **************************************************/ { BufferNode *node; unsigned long processed=0; for(node=info->head; node!=NULL; node = node->next) { PR_ASSERT(processed < info->totalLen); PR_ASSERT(node->data != NULL); PR_ASSERT(node->len > 0); memcpy(pkcs7Bytes+processed, node->data, node->len); processed += node->len; } PR_ASSERT( processed == info->totalLen ); } finish: /************************************************** * Free allocated resources **************************************************/ if( cinfo != NULL) { SEC_PKCS7DestroyContentInfo(cinfo); } JSS_DerefByteArray(env, pkcs7ByteArray, pkcs7Bytes, 0); if( info != NULL ) { destroyEncoderCallbackInfo(info); } /************************************************** * Return the PKCS #7 information in a byte array, or NULL if an * exception occurred **************************************************/ PR_ASSERT( (*env)->ExceptionOccurred(env)!=NULL || pkcs7ByteArray!=NULL ); return pkcs7ByteArray; } /*************************************************************************** * getCerts * * Gathers all certificates of the given type into a Java array. */ static jobjectArray getCerts(JNIEnv *env, PK11CertListType type) { jobjectArray certArray = NULL; jclass certClass; jobject certObject; CERTCertList *certList = NULL; CERTCertListNode *node; int numCerts, i; certList = PK11_ListCerts(type, NULL); if( certList == NULL ) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Unable to list certificates"); goto finish; } /* first count the damn certs */ numCerts = 0; for( node = CERT_LIST_HEAD(certList); ! CERT_LIST_END(node, certList); node = CERT_LIST_NEXT(node) ) { ++numCerts; } /************************************************** * Create array of Java certificates **************************************************/ certClass = (*env)->FindClass(env, X509_CERT_CLASS); if(certClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } certArray = (*env)->NewObjectArray( env, numCerts, certClass, NULL ); if( certArray == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } PR_ASSERT( (*env)->ExceptionOccurred(env) == NULL ); /************************************************** * Put all the certs in the array **************************************************/ i = 0; for( node = CERT_LIST_HEAD(certList); ! CERT_LIST_END(node, certList); node = CERT_LIST_NEXT(node) ) { PR_ASSERT( i < numCerts ); certObject = JSS_PK11_wrapCert(env, &(node->cert)); if( certObject == NULL ) { goto finish; } (*env)->SetObjectArrayElement(env, certArray, i, certObject); if( (*env)->ExceptionOccurred(env) ) { goto finish; } ++i; } PR_ASSERT( i == numCerts ); finish: if( certList != NULL ) { CERT_DestroyCertList(certList); } return certArray; } /*********************************************************************** * CryptoManager.getCACerts */ JNIEXPORT jobjectArray JNICALL Java_org_mozilla_jss_CryptoManager_getCACerts (JNIEnv *env, jobject this) { return getCerts(env, PK11CertListCA); } /*********************************************************************** * CryptoManager.getPermCerts */ JNIEXPORT jobjectArray JNICALL Java_org_mozilla_jss_CryptoManager_getPermCerts (JNIEnv *env, jobject this) { return getCerts(env, PK11CertListUnique); } /* Imports a CRL, and stores it into the cert7.db * * @param the DER-encoded CRL. */ JNIEXPORT void JNICALL Java_org_mozilla_jss_CryptoManager_importCRLNative (JNIEnv *env, jobject this, jbyteArray der_crl, jstring url_jstr, jint rl_type) { CERTCertDBHandle *certdb = CERT_GetDefaultCertDB(); CERTSignedCrl *crl = NULL; SECItem *packageItem = NULL; int status = SECFailure; char *url = NULL; const char *errmsg = NULL; /*************************************************** * Validate arguments ***************************************************/ PR_ASSERT( env!=NULL && this!=NULL ); if(der_crl == NULL) { PR_ASSERT(PR_FALSE); /* XXX need new exception here */ JSS_throwMsg(env, CERTIFICATE_ENCODING_EXCEPTION, "CRL package is NULL"); goto finish; } PR_ASSERT(certdb != NULL); /* convert CRL byte[] into secitem */ packageItem = JSS_ByteArrayToSECItem(env, der_crl); if ( packageItem == NULL ) { goto finish; } url = (char *)JSS_RefJString(env, url_jstr); if (url_jstr != NULL && url == NULL) { goto finish; } crl = CERT_ImportCRL( certdb, packageItem, url, rl_type, NULL); if( crl == NULL ) { status = PR_GetError(); errmsg = NULL; switch (status) { case SEC_ERROR_OLD_CRL: case SEC_ERROR_OLD_KRL: /* not an error - leave as NULL */ errmsg = NULL; goto finish; case SEC_ERROR_CRL_EXPIRED: errmsg = "CRL Expired"; break; case SEC_ERROR_KRL_EXPIRED: errmsg = "KRL Expired"; break; case SEC_ERROR_CRL_NOT_YET_VALID: errmsg = "CRL Not yet valid"; break; case SEC_ERROR_KRL_NOT_YET_VALID: errmsg = "KRL Not yet valid"; break; case SEC_ERROR_CRL_INVALID: errmsg = "Invalid encoding of CRL"; break; case SEC_ERROR_KRL_INVALID: errmsg = "Invalid encoding of KRL"; break; case SEC_ERROR_BAD_DATABASE: errmsg = "Database error"; break; default: /* printf("NSS ERROR = %d\n",status); */ errmsg = "Failed to import Revocation List"; } if (errmsg) { JSS_throwMsgPrErr(env, CRL_IMPORT_EXCEPTION, errmsg); } } finish: if (packageItem) { SECITEM_FreeItem(packageItem, PR_TRUE /*freeit*/); } JSS_DerefJString(env, url_jstr, url); if (crl) { SEC_DestroyCrl(crl); } } /*********************************************************************** * CryptoManager.verifyCertificateNow * * Called by java_org_mozilla_jss_CryptoManager_verifyCertificateNowCUNative */ SECStatus verifyCertificateNow(JNIEnv *env, jobject self, jstring nickString, jboolean checkSig, jint required_certificateUsage, SECCertificateUsage *currUsage) { SECStatus rv = SECFailure; SECCertificateUsage certificateUsage; CERTCertificate *cert=NULL; const char *nickname = NULL; nickname = JSS_RefJString(env, nickString); if( nickname == NULL ) { goto finish; } int ocspPolicy = JSSL_getOCSPPolicy(); certificateUsage = required_certificateUsage; cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), nickname); if (cert == NULL) { char *message = PR_smprintf("Certificate not found: %s", nickname); JSS_throwMsg(env, OBJECT_NOT_FOUND_EXCEPTION, message); PR_smprintf_free(message); goto finish; } else { /* 0 for certificateUsage in call to CERT_VerifyCertificateNow will * retrieve the current valid usage into currUsage */ if( ocspPolicy == OCSP_LEAF_AND_CHAIN_POLICY) { rv = JSSL_verifyCertPKIX( cert, certificateUsage, NULL /* pin arg */, ocspPolicy, NULL, currUsage); /* we need to do this just to get the cert usages, the pkix version doesn't seem to honor the method to get the usages as of yet. Let the PKIX call only determine the final fate. */ if(rv == SECSuccess) { CERT_VerifyCertificateNow(CERT_GetDefaultCertDB(), cert, checkSig, certificateUsage, NULL, currUsage ); } } else { rv = CERT_VerifyCertificateNow(CERT_GetDefaultCertDB(), cert, checkSig, certificateUsage, NULL, currUsage ); } if ((rv == SECSuccess) && certificateUsage == 0x0000) { if (*currUsage == ( certUsageUserCertImport | certUsageVerifyCA | certUsageProtectedObjectSigner | certUsageAnyCA )) { /* the cert is good for nothing The folllowing usages cannot be verified: certUsageAnyCA certUsageProtectedObjectSigner certUsageUserCertImport certUsageVerifyCA (0x0b80) */ rv =SECFailure; } } } finish: JSS_DerefJString(env, nickString, nickname); if(cert != NULL) { CERT_DestroyCertificate(cert); } return rv; } /*********************************************************************** * CryptoManager.verifyCertificateNowNative * * Returns JNI_TRUE if success, JNI_FALSE otherwise */ JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_CryptoManager_verifyCertificateNowNative(JNIEnv *env, jobject self, jstring nickString, jboolean checkSig, jint required_certificateUsage) { SECStatus rv = SECFailure; SECCertificateUsage certificateUsage; SECCertificateUsage currUsage; /* unexposed for now */ CERTCertificate *cert=NULL; const char *nickname = NULL; nickname = JSS_RefJString(env, nickString); if( nickname == NULL ) { goto finish; } int ocspPolicy = JSSL_getOCSPPolicy(); certificateUsage = required_certificateUsage; cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), nickname); if (cert == NULL) { char *message = PR_smprintf("Certificate not found: %s", nickname); JSS_throwMsg(env, OBJECT_NOT_FOUND_EXCEPTION, message); PR_smprintf_free(message); goto finish; } else { /* 0 for certificateUsage in call to CERT_VerifyCertificateNow to * just get the current usage (which we are not passing back for now * but will bypass the certificate usage check */ if( ocspPolicy == OCSP_LEAF_AND_CHAIN_POLICY) { rv= JSSL_verifyCertPKIX( cert, certificateUsage, NULL /* pin arg */, ocspPolicy, NULL, &currUsage); /* we need to do this just to get the cert usages, the pkix version doesn't seem to honor the method to get the usages as of yet. Let the PKIX call only determine the final fate. */ if(rv == SECSuccess) { CERT_VerifyCertificateNow(CERT_GetDefaultCertDB(), cert, checkSig, certificateUsage, NULL, &currUsage ); } } else { rv = CERT_VerifyCertificateNow(CERT_GetDefaultCertDB(), cert, checkSig, certificateUsage, NULL, &currUsage ); } } finish: JSS_DerefJString(env, nickString, nickname); if(cert != NULL) { CERT_DestroyCertificate(cert); } if( rv == SECSuccess) { return JNI_TRUE; } else { return JNI_FALSE; } } /*********************************************************************** * CryptoManager.verifyCertificateNowCUNative * * Returns jint which contains bits in SECCertificateUsage that reflects * the cert usage(s) that the cert is good for * if the cert is good for nothing, returned value is * (0x0b80): * certUsageUserCertImport | * certUsageVerifyCA | * certUsageProtectedObjectSigner | * certUsageAnyCA */ JNIEXPORT jint JNICALL Java_org_mozilla_jss_CryptoManager_verifyCertificateNowCUNative(JNIEnv *env, jobject self, jstring nickString, jboolean checkSig) { SECStatus VARIABLE_MAY_NOT_BE_USED rv = SECFailure; SECCertificateUsage currUsage = 0x0000; rv = verifyCertificateNow(env, self, nickString, checkSig, 0, &currUsage); /* rv is ignored */ return currUsage; } void JSS_VerifyCertificate(JNIEnv *env, CERTCertificate *cert, jboolean checkSig, jint usage) { jint certificateUsage; SECCertificateUsage currUsage = 0x0000; /* unexposed for now */ SECStatus rv = SECFailure; int ocspPolicy = JSSL_getOCSPPolicy(); certificateUsage = usage; /* 0 for certificateUsage in call to CERT_VerifyCertificateNow will * retrieve the current valid usage into currUsage */ if( ocspPolicy == OCSP_LEAF_AND_CHAIN_POLICY) { rv = JSSL_verifyCertPKIX( cert, certificateUsage, NULL /* pin arg */, ocspPolicy, NULL, &currUsage); /* we need to do this just to get the cert usages, the pkix version doesn't seem to honor the method to get the usages as of yet. Let the PKIX call only determine the final fate. */ if(rv == SECSuccess) { CERT_VerifyCertificateNow(CERT_GetDefaultCertDB(), cert, checkSig, certificateUsage, NULL, &currUsage ); } } else { rv = CERT_VerifyCertificateNow(CERT_GetDefaultCertDB(), cert, checkSig, certificateUsage, NULL, &currUsage); } if (rv != SECSuccess) { JSS_throwMsgPrErr(env, CERTIFICATE_EXCEPTION, "Invalid certificate"); return; } if ((certificateUsage == 0x0000) && (currUsage == ( certUsageUserCertImport | certUsageVerifyCA | certUsageProtectedObjectSigner | certUsageAnyCA ))) { /* The certificate is good for nothing. * The following usages cannot be verified: * certUsageAnyCA * certUsageProtectedObjectSigner * certUsageUserCertImport * certUsageVerifyCA * (0x0b80) */ JSS_throwMsgPrErr(env, CERTIFICATE_EXCEPTION, "Unusable certificate"); return; } } /*********************************************************************** * CryptoManager.verifyCertificateNowNative2 * * Verify a certificate that exists in the given cert database, * check if it's valid and that we trust the issuer. Verify time * against now. * @param nickname nickname of the certificate to verify. * @param checkSig verify the signature of the certificate * @param certificateUsage see certificate usage defined to verify certificate * * @exception InvalidNicknameException If the nickname is null. * @exception ObjectNotFoundException If no certificate could be found * with the given nickname. * @exception CertificateException If certificate is invalid. */ JNIEXPORT void JNICALL Java_org_mozilla_jss_CryptoManager_verifyCertificateNowNative2(JNIEnv *env, jobject self, jstring nickString, jboolean checkSig, jint required_certificateUsage) { CERTCertificate *cert = NULL; const char *nickname = NULL; if (nickString == NULL) { JSS_throwMsg(env, INVALID_NICKNAME_EXCEPTION, "Missing certificate nickname"); goto finish; } nickname = JSS_RefJString(env, nickString); if (nickname == NULL) { JSS_throwMsg(env, INVALID_NICKNAME_EXCEPTION, "Missing certificate nickname"); goto finish; } cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), nickname); if (cert == NULL) { char *msgBuf; msgBuf = PR_smprintf("Certificate not found: %s", nickname); JSS_throwMsg(env, OBJECT_NOT_FOUND_EXCEPTION, msgBuf); PR_Free(msgBuf); goto finish; } JSS_VerifyCertificate(env, cert, checkSig, required_certificateUsage); finish: JSS_DerefJString(env, nickString, nickname); CERT_DestroyCertificate(cert); } JNIEXPORT void JNICALL Java_org_mozilla_jss_CryptoManager_verifyCertificateNowNative3(JNIEnv *env, jobject self, jobject Cert, jboolean checkSig, jint required_certificateUsage) { CERTCertificate *cert = NULL; if (JSS_PK11_getCertPtr(env, Cert, &cert) != PR_SUCCESS) { PR_ASSERT((*env)->ExceptionOccurred(env) != NULL); return; } JSS_VerifyCertificate(env, cert, checkSig, required_certificateUsage); } /*********************************************************************** * CryptoManager.verifyCertNowNative * note: this calls obsolete NSS function * Returns JNI_TRUE if success, JNI_FALSE otherwise */ JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_CryptoManager_verifyCertNowNative(JNIEnv *env, jobject self, jstring nickString, jboolean checkSig, jint cUsage) { SECStatus rv = SECFailure; SECCertUsage certUsage; CERTCertificate *cert=NULL; const char *nickname = NULL; nickname = JSS_RefJString(env, nickString); if( nickname == NULL ) { goto finish; } int ocspPolicy = JSSL_getOCSPPolicy(); certUsage = cUsage; cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), nickname); if (cert == NULL) { char *message = PR_smprintf("Certificate not found: %s", nickname); JSS_throwMsg(env, OBJECT_NOT_FOUND_EXCEPTION, message); PR_smprintf_free(message); goto finish; } else { if( ocspPolicy == OCSP_LEAF_AND_CHAIN_POLICY) { rv = JSSL_verifyCertPKIX( cert, certUsage, NULL /* pin arg */, ocspPolicy, NULL, NULL); } else { rv = CERT_VerifyCertNow(CERT_GetDefaultCertDB(), cert, checkSig, certUsage, NULL ); } } finish: JSS_DerefJString(env, nickString, nickname); if(cert != NULL) { CERT_DestroyCertificate(cert); } if( rv == SECSuccess) { return JNI_TRUE; } else { return JNI_FALSE; } } /*********************************************************************** * CryptoManager.verifyCertNative * * Returns JNI_TRUE if success, JNI_FALSE otherwise */ JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_CryptoManager_verifyCertTempNative(JNIEnv *env, jobject self, jbyteArray packageArray,jboolean checkSig, jint cUsage) { SECStatus rv = SECFailure; SECCertUsage certUsage; SECItem *derCerts[2] = { NULL, NULL }; CERTCertificate **certArray = NULL; CERTCertDBHandle *certdb = CERT_GetDefaultCertDB(); /*************************************************** * Validate arguments ***************************************************/ if (packageArray == NULL) { JSS_throwMsg(env, CERTIFICATE_ENCODING_EXCEPTION, "Certificate package is NULL"); goto finish; } PR_ASSERT(certdb != NULL); derCerts[0] = JSS_ByteArrayToSECItem(env, packageArray); derCerts[1] = NULL; int ocspPolicy = JSSL_getOCSPPolicy(); rv = CERT_ImportCerts(certdb, cUsage, 1, derCerts, &certArray, PR_FALSE /*temp Certs*/, PR_FALSE /*caOnly*/, NULL); if ( rv != SECSuccess || certArray == NULL || certArray[0] == NULL) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Unable to insert certificate" " into temporary database"); goto finish; } certUsage = cUsage; if( ocspPolicy == OCSP_LEAF_AND_CHAIN_POLICY) { rv = JSSL_verifyCertPKIX( certArray[0], certUsage, NULL /* pin arg */, ocspPolicy, NULL, NULL); } else { rv = CERT_VerifyCertNow(certdb, certArray[0], checkSig, certUsage, NULL ); } finish: /* this checks for NULL */ CERT_DestroyCertArray(certArray, 1); if (derCerts[0]) { SECITEM_FreeItem(derCerts[0], PR_TRUE /*freeit*/); } if ( rv == SECSuccess) { return JNI_TRUE; } else { return JNI_FALSE; } } /*********************************************************************** * CryptoManager.importDERCertNative */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_CryptoManager_importDERCertNative(JNIEnv *env, jobject self, jbyteArray cert, int usage, jboolean permanent, jstring nickname) { char *nickname_raw = NULL; jsize derCertLen; SECItem *derCert = calloc(1, sizeof(SECItem)); CERTCertificate **retCert = NULL; PR_ASSERT(env != NULL &&& self != NULL); if (cert == NULL) { return NULL; } if (nickname != NULL) { nickname_raw = (char *)JSS_RefJString(env, nickname); } derCert->type = siDERCertBuffer; if (!JSS_RefByteArray(env, cert, (signed char **)&derCert->data, &derCertLen)) { return NULL; } PR_ASSERT(derCertLen > 0); derCert->len = (unsigned int)derCertLen; /* At the time of writing, caOnly is an unused parameter. */ if (CERT_ImportCerts(CERT_GetDefaultCertDB(), usage, 1, &derCert, &retCert, permanent, PR_FALSE, nickname_raw) != SECSuccess) { JSS_DerefByteArray(env, cert, derCert->data, JNI_ABORT); JSS_DerefJString(env, nickname, nickname_raw); JSS_throwMsgPortErr(env, INVALID_PARAMETER_EXCEPTION, "Unable to import certificate"); return NULL; } JSS_DerefByteArray(env, cert, derCert->data, JNI_ABORT); JSS_DerefJString(env, nickname, nickname_raw); return JSS_PK11_wrapCert(env, retCert); } jss-5.0.0/src/main/java/org/mozilla/jss/SecretDecoderRing/000077500000000000000000000000001412550063600233415ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/SecretDecoderRing/Decryptor.java000066400000000000000000000066211412550063600261640ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.SecretDecoderRing; import java.security.GeneralSecurityException; import java.security.InvalidKeyException; import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.EncryptionAlgorithm; import org.mozilla.jss.crypto.TokenException; /** * Decrypts data with the SecretDecoderRing. */ public class Decryptor { private CryptoToken token; private KeyManager keyManager; /** * Creates a Decryptor for use with the given CryptoToken. */ public Decryptor(CryptoToken token) { this.token = token; this.keyManager = new KeyManager(token); } /** * Decrypts the given ciphertext. It must have been created previously * with the SecretDecoderRing, either the JSS version or the NSS version. * The key used for decryption must exist on the token that was passed * into the constructor. The token will be searched for a key whose keyID * matches the keyID in the encoded SecretDecoderRing result. * * @param ciphertext A DER-encoded Encoding object, created from a previous * call to Encryptor.encrypt(), or with the NSS SecretDecoderRing. * @return The decrypted plaintext. * @throws InvalidKeyException If no key can be found with the matching * keyID. */ public byte[] decrypt(byte[] ciphertext) throws NotInitializedException, GeneralSecurityException, TokenException { CryptoManager cm = CryptoManager.getInstance(); CryptoToken savedToken = cm.getThreadToken(); try { cm.setThreadToken(token); // // decode ASN1 // Encoding encoding = (Encoding) ASN1Util.decode(Encoding.getTemplate(), ciphertext); // // lookup the algorithm // EncryptionAlgorithm alg = EncryptionAlgorithm.fromOID( encoding.getEncryptionOID() ); // // Lookup the key // SecretKey key = keyManager.lookupKey(alg, encoding.getKeyID()); if( key == null ) { throw new InvalidKeyException("No matching key found"); } // // do the decryption // IvParameterSpec ivSpec = new IvParameterSpec(encoding.getIv()); Cipher cipher = Cipher.getInstance(alg.toString(), Encryptor.PROVIDER); cipher.init(Cipher.DECRYPT_MODE, key, ivSpec); byte[] paddedPtext = cipher.doFinal(encoding.getCiphertext()); return org.mozilla.jss.crypto.Cipher.unPad(paddedPtext, alg.getBlockSize() ); } catch(InvalidBERException ibe) { throw new GeneralSecurityException(ibe.toString()); } catch(IllegalStateException ise) { throw new GeneralSecurityException(ise.toString()); } finally { cm.setThreadToken(savedToken); } } } jss-5.0.0/src/main/java/org/mozilla/jss/SecretDecoderRing/Encoding.java000066400000000000000000000071731412550063600257420ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.SecretDecoderRing; import org.mozilla.jss.asn1.*; import org.mozilla.jss.pkix.primitive.*; import java.io.*; /** * An ASN.1 class for encoding the SecretDecoderRing result. * This class is used internally by the SecretDecoderRing. * You need not use this class directly in order to use the SecretDecoderRing. */ public class Encoding implements ASN1Value { private SEQUENCE seq = new SEQUENCE(); private byte[] iv; private OBJECT_IDENTIFIER encOID; private byte[] ctext; private byte[] keyID; public Encoding(byte[] keyID, byte[] iv, OBJECT_IDENTIFIER encOID, byte[] ctext) { this.keyID = keyID; this.iv = iv; this.encOID = encOID; this.ctext = ctext; AlgorithmIdentifier algID = new AlgorithmIdentifier( encOID, new OCTET_STRING(iv) ); seq.addElement(new OCTET_STRING(keyID)); seq.addElement(algID); seq.addElement(new OCTET_STRING(ctext)); } public byte[] getKeyID() { return keyID; } public byte[] getIv() { return iv; } public OBJECT_IDENTIFIER getEncryptionOID() { return encOID; } public byte[] getCiphertext() { return ctext; } public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { seq.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * An ASN.1 class for decoding the SecretDecoderRing result. * This class is used internally by the SecretDecoderRing. * You need not use this class directly in order to use the * SecretDecoderRing. */ public static class Template extends SEQUENCE.Template { private SEQUENCE.Template template; public Template() { template = new SEQUENCE.Template(); template.addElement(OCTET_STRING.getTemplate() ); template.addElement(AlgorithmIdentifier.getTemplate() ); template.addElement(OCTET_STRING.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { SEQUENCE seq = (SEQUENCE) template.decode(implicitTag, istream); OCTET_STRING keyID = (OCTET_STRING) seq.elementAt(0); AlgorithmIdentifier algID = (AlgorithmIdentifier) seq.elementAt(1); OCTET_STRING ivOS = (OCTET_STRING) ((ANY)algID.getParameters()).decodeWith( OCTET_STRING.getTemplate()); OCTET_STRING ctextOS = (OCTET_STRING)seq.elementAt(2); return new Encoding(keyID.toByteArray(), ivOS.toByteArray(), algID.getOID(), ctextOS.toByteArray()); } } } jss-5.0.0/src/main/java/org/mozilla/jss/SecretDecoderRing/Encryptor.java000066400000000000000000000076111412550063600261760ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.SecretDecoderRing; import java.security.*; import javax.crypto.*; import javax.crypto.spec.*; import org.mozilla.jss.asn1.*; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.EncryptionAlgorithm; import org.mozilla.jss.crypto.TokenException; /** * Encrypts data with the SecretDecoderRing. */ public class Encryptor { private CryptoToken token; private byte[] keyID; private SecretKey key; private EncryptionAlgorithm alg; private KeyManager keyManager; /** * The default encryption algorithm, currently DES3_CBC. */ public static final EncryptionAlgorithm DEFAULT_ENCRYPTION_ALG = EncryptionAlgorithm.DES3_CBC; static final String PROVIDER = "Mozilla-JSS"; static final String RNG_ALG = "pkcs11prng"; /** * Creates an Encryptor on the given CryptoToken, using the key with * the given keyID and algorithm * @param token The CryptoToken to use for encryption. The key must * reside on this token. * @param keyID The keyID of the key to use for encryption. This key * must have been generated on this token with KeyManager. * @param alg The EncryptionAlgorithm this key will be used for. * @throws InvalidKeyException If no key exists on this token with this * keyID. */ public Encryptor(CryptoToken token, byte[] keyID, EncryptionAlgorithm alg) throws TokenException, InvalidKeyException { this.token = token; this.keyID = keyID; this.alg = alg; this.keyManager = new KeyManager(token); // make sure this key exists on the token key = keyManager.lookupKey(alg, keyID); if( key == null ) { throw new InvalidKeyException("Key not found"); } // make sure key matches algorithm // !!! not sure how to do this } /** * Encrypts a byte array. * @param plaintext The plaintext bytes to be encrypted. * @return The ciphertext. This is actually a DER-encoded Encoding * object. It contains the keyID, AlgorithmIdentifier, and the encrypted * plaintext. It is compatible with the SDRResult created by NSS's * SecretDecoderRing. */ public byte[] encrypt(byte[] plaintext) throws NotInitializedException, GeneralSecurityException, InvalidBERException { CryptoManager cm = CryptoManager.getInstance(); CryptoToken savedToken = cm.getThreadToken(); try { cm.setThreadToken(token); // // generate an IV // byte[] iv = new byte[alg.getIVLength()]; SecureRandom rng = SecureRandom.getInstance(RNG_ALG, PROVIDER); rng.nextBytes(iv); IvParameterSpec ivSpec = new IvParameterSpec(iv); // // do the encryption // Cipher cipher = Cipher.getInstance(alg.toString(),PROVIDER); cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec); byte[] paddedPtext = org.mozilla.jss.crypto.Cipher.pad( plaintext, alg.getBlockSize() ); byte[] rawCtext = cipher.doFinal(paddedPtext); // // package the encrypted content and IV // Encoding encoding = new Encoding(keyID, iv, alg.toOID(), rawCtext); return ASN1Util.encode(encoding); } catch(IllegalStateException ise ) { throw new GeneralSecurityException(ise.toString()); } finally { cm.setThreadToken(savedToken); } } } jss-5.0.0/src/main/java/org/mozilla/jss/SecretDecoderRing/KeyManager.c000066400000000000000000000237151412550063600255400ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "_jni/org_mozilla_jss_SecretDecoderRing_KeyManager.h" #include #include #include #include #include #include #include JNIEXPORT void JNICALL Java_org_mozilla_jss_SecretDecoderRing_KeyManager_generateKeyNative (JNIEnv *env, jobject this, jobject tokenObj, jobject algObj, jbyteArray keyIDba, jint keySize) { PK11SlotInfo *slot = NULL; CK_MECHANISM_TYPE mech; PK11SymKey *symk = NULL; SECItem *keyID = NULL; /* get the slot */ if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS ) { goto finish; } if( PK11_Authenticate(slot, PR_TRUE /*load certs*/, NULL /*wincx*/) != SECSuccess) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to login to token"); goto finish; } /* get the key ID */ keyID = JSS_ByteArrayToSECItem(env, keyIDba); if( keyID == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } /* get the algorithm */ mech = JSS_getPK11MechFromAlg(env, algObj); if( mech == CKM_INVALID_MECHANISM) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to find PKCS #11 " "mechanism for key generation algorithm"); goto finish; } /* generate the key */ symk = PK11_TokenKeyGen(slot, mech, NULL /*param*/, keySize, keyID, PR_TRUE /* isToken */, NULL /*wincx*/); if( symk == NULL ) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to generate token symmetric key"); goto finish; } finish: if( symk != NULL ) { PK11_FreeSymKey(symk); } if( keyID != NULL ) { SECITEM_FreeItem(keyID, PR_TRUE /*freeit*/); } return; } JNIEXPORT void JNICALL Java_org_mozilla_jss_SecretDecoderRing_KeyManager_generateUniqueNamedKeyNative (JNIEnv *env, jobject this, jobject tokenObj, jobject algObj, jbyteArray keyIDba, jint keySize, jstring nickname) { PK11SlotInfo *slot = NULL; CK_MECHANISM_TYPE mech; PK11SymKey *symk = NULL; SECItem *keyID = NULL; const char *keyname = NULL; SECStatus status; /* get the slot */ if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS ) { goto finish; } if( PK11_Authenticate(slot, PR_TRUE /*load certs*/, NULL /*wincx*/) != SECSuccess) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to login to token"); goto finish; } /* get the key ID */ keyID = JSS_ByteArrayToSECItem(env, keyIDba); if( keyID == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } /* get the algorithm */ mech = JSS_getPK11MechFromAlg(env, algObj); if( mech == CKM_INVALID_MECHANISM) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to find PKCS #11 " "mechanism for key generation algorithm"); goto finish; } /* generate the key */ symk = PK11_TokenKeyGen(slot, mech, NULL /*param*/, keySize, keyID, PR_TRUE /* isToken */, NULL /*wincx*/); if( symk == NULL ) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to generate token symmetric key"); goto finish; } /* convert the Java String into a native "C" string */ keyname = JSS_RefJString(env, nickname); /* name the key */ status = PK11_SetSymKeyNickname( symk, keyname ); if( status != SECSuccess ) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to name token symmetric key"); } finish: if( symk != NULL ) { PK11_FreeSymKey(symk); } if( keyID != NULL ) { SECITEM_FreeItem(keyID, PR_TRUE /*freeit*/); } /* free the native "C" string */ JSS_DerefJString(env, nickname, keyname); return; } JNIEXPORT jobject JNICALL Java_org_mozilla_jss_SecretDecoderRing_KeyManager_lookupKeyNative (JNIEnv *env, jobject this, jobject tokenObj, jobject algObj, jbyteArray keyIDba) { PK11SlotInfo *slot = NULL; PK11SymKey *symk = NULL; SECItem *keyID = NULL; jobject symkObj = NULL; CK_MECHANISM_TYPE mech; /* get the slot */ if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS ) { goto finish; } if( PK11_Authenticate(slot, PR_TRUE /*load certs*/, NULL /*wincx*/) != SECSuccess) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to login to token"); goto finish; } /* get the key ID */ keyID = JSS_ByteArrayToSECItem(env, keyIDba); if( keyID == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } /* get the algorithm */ mech = JSS_getPK11MechFromAlg(env, algObj); if( mech == CKM_INVALID_MECHANISM) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to find PKCS #11 " "mechanism for key generation algorithm"); goto finish; } symk = PK11_FindFixedKey(slot, mech, keyID, NULL /*wincx*/); if( symk != NULL ) { symkObj = JSS_PK11_wrapSymKey(env, &symk); } finish: if( symk != NULL ) { PK11_FreeSymKey(symk); } if( keyID != NULL ) { SECITEM_FreeItem(keyID, PR_TRUE /*freeit*/); } return symkObj; } JNIEXPORT jobject JNICALL Java_org_mozilla_jss_SecretDecoderRing_KeyManager_lookupUniqueNamedKeyNative (JNIEnv *env, jobject this, jobject tokenObj, jobject algObj, jstring nickname) { PK11SlotInfo *slot = NULL; CK_MECHANISM_TYPE mech; const char *keyname = NULL; char *name = NULL; int count = 0; int keys_found = 0; PK11SymKey *symKey = NULL; PK11SymKey *nextSymKey = NULL; jobject symKeyObj = NULL; /* get the slot */ if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS ) { goto finish; } if( PK11_Authenticate(slot, PR_TRUE /*load certs*/, NULL /*wincx*/) != SECSuccess) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to login to token"); goto finish; } /* get the algorithm -- although this is not currently used */ mech = JSS_getPK11MechFromAlg(env, algObj); if( mech == CKM_INVALID_MECHANISM) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to find PKCS #11 " "mechanism for key generation algorithm"); goto finish; } /* convert the Java String into a native "C" string */ keyname = JSS_RefJString(env, nickname); /* initialize the symmetric key list. */ symKey = PK11_ListFixedKeysInSlot( /* slot */ slot, /* nickname */ NULL, /* wincx */ NULL ); /* iterate through the symmetric key list. */ while( symKey != NULL ) { name = PK11_GetSymKeyNickname( /* symmetric key */ symKey ); if( name != NULL ) { if( keyname != NULL ) { if( PL_strcmp( keyname, name ) == 0 ) { keys_found++; } } PORT_Free(name); } nextSymKey = PK11_GetNextSymKey( /* symmetric key */ symKey ); PK11_FreeSymKey( /* symmetric key */ symKey ); symKey = nextSymKey; count++; } /* case 1: the token is empty */ if( count == 0 ) { /* the specified token is empty */ goto finish; } /* case 2: the specified key is not on this token */ if( ( keyname != NULL ) && ( keys_found == 0 ) ) { /* the key called "keyname" could not be found */ goto finish; } /* case 3: the specified key exists more than once on this token */ if( keys_found != 1 ) { /* more than one key called "keyname" was found on this token */ JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Duplicate named keys exist on this token"); goto finish; } /* Re-initialize the symmetric key list. */ symKey = PK11_ListFixedKeysInSlot( /* slot */ slot, /* nickname */ NULL, /* wincx */ NULL ); /* Reiterate through the symmetric key list once more, */ /* this time returning an actual reference to the key. */ while( symKey != NULL ) { name = PK11_GetSymKeyNickname( /* symmetric key */ symKey ); if( name != NULL ) { if( keyname != NULL ) { if( PL_strcmp( keyname, name ) == 0 ) { symKeyObj = JSS_PK11_wrapSymKey(env, &symKey); PORT_Free(name); goto finish; } } PORT_Free(name); } nextSymKey = PK11_GetNextSymKey( /* symmetric key */ symKey ); PK11_FreeSymKey( /* symmetric key */ symKey ); symKey = nextSymKey; } finish: if( symKey != NULL ) { PK11_FreeSymKey(symKey); } /* free the native "C" string */ JSS_DerefJString(env, nickname, keyname); return symKeyObj; } JNIEXPORT void JNICALL Java_org_mozilla_jss_SecretDecoderRing_KeyManager_deleteKeyNative (JNIEnv *env, jobject this, jobject tokenObj, jobject key) { PK11SlotInfo *slot = NULL; PK11SymKey *symk = NULL; /* get the slot */ if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS ) { goto finish; } if( PK11_Authenticate(slot, PR_TRUE /*load certs*/, NULL /*wincx*/) != SECSuccess) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to login to token"); goto finish; } /* get the key pointer */ if( JSS_PK11_getSymKeyPtr(env, key, &symk) != PR_SUCCESS) { goto finish; } if( PK11_DeleteTokenSymKey(symk) != SECSuccess ) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to delete token symmetric key"); goto finish; } finish: /* don't free symk or slot, they are owned by their Java objects */ return; } jss-5.0.0/src/main/java/org/mozilla/jss/SecretDecoderRing/KeyManager.java000066400000000000000000000252011412550063600262270ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.SecretDecoderRing; import java.security.*; import javax.crypto.*; import org.mozilla.jss.crypto.*; /** * Creates, finds, and deletes keys for SecretDecoderRing. */ public class KeyManager { private static final int KEYID_LEN = 16; private static final String RNG_ALG = "pkcs11prng"; private static final String RNG_PROVIDER = "Mozilla-JSS"; /** * The default key generation algorithm, currently DES3. */ public static final KeyGenAlgorithm DEFAULT_KEYGEN_ALG = KeyGenAlgorithm.DES3; /** * The default key size (in bytes). This is only relevant for algorithms * with variable-length keys, such as AES. */ public static final int DEFAULT_KEYSIZE = 0; private CryptoToken token; /** * Creates a new KeyManager using the given CryptoToken. * @param token The token on which this KeyManager operates. */ public KeyManager(CryptoToken token) { if( token == null ) { throw new NullPointerException("token is null"); } this.token = token; } /** * Generates an SDR key with the default algorithm and key size. * The default algorithm is stored in the constant DEFAULT_KEYGEN_ALG. * The default key size is stored in the constant DEFAULT_KEYSIZE. * @return The keyID of the generated key. A random keyID will be chosen * that is not currently used on the token. The keyID must be stored * by the application in order to use this key for encryption in the * future. */ public byte[] generateKey() throws TokenException { return generateKey(DEFAULT_KEYGEN_ALG, DEFAULT_KEYSIZE); } /** * Generates an SDR key with the given algorithm and key size. * @param keySize Length of key in bytes. This is only relevant for * algorithms that take more than one key size. Otherwise it can just * be set to 0. * @return The keyID of the generated key. A random keyID will be chosen * that is not currently used on the token. The keyID must be stored * by the application in order to use this key for encryption in the * future. */ public byte[] generateKey(KeyGenAlgorithm alg, int keySize) throws TokenException { if( alg == null ) { throw new NullPointerException("alg is null"); } byte[] keyID = generateUnusedKeyID(); generateKeyNative(token, alg, keyID, keySize); return keyID; } /** * @param keySize Key length in bytes. */ private native void generateKeyNative(CryptoToken token, KeyGenAlgorithm alg, byte[] keyID, int keySize); /** * Generates an SDR key with the default algorithm and key size. * and names it with the specified nickname. * The default algorithm is stored in the constant DEFAULT_KEYGEN_ALG. * The default key size is stored in the constant DEFAULT_KEYSIZE. * @param nickname the name of the symmetric key. Duplicate keynames * will be checked for, and are not allowed. * @return The keyID of the generated key. A random keyID will be chosen * that is not currently used on the token. The keyID must be stored * by the application in order to use this key for encryption in the * future. */ public byte[] generateUniqueNamedKey(String nickname) throws TokenException { return generateUniqueNamedKey(DEFAULT_KEYGEN_ALG, DEFAULT_KEYSIZE, nickname); } /** * Generates an SDR key with the given algorithm, key size, and nickname. * @param alg The algorithm that this key will be used for. * This is necessary because it will be stored along with the * key for later use by the security library. * @param keySize Length of key in bytes. This is only relevant for * algorithms that take more than one key size. Otherwise it can just * be set to 0. * @param nickname the name of the symmetric key. Duplicate keynames * will be checked for, and are not allowed. * @return The keyID of the generated key. A random keyID will be chosen * that is not currently used on the token. The keyID must be stored * by the application in order to use this key for encryption in the * future. */ public byte[] generateUniqueNamedKey(KeyGenAlgorithm alg, int keySize, String nickname) throws TokenException { // always strip all preceding/trailing whitespace // from passed-in String parameters if( nickname != null ) { nickname = nickname.trim(); } if( alg == null ) { throw new NullPointerException("alg is null"); } // disallow duplicates (i. e. - symmetric keys with the same name) if( uniqueNamedKeyExists(nickname) ) { throw new NullPointerException("duplicate symmetric key"); } byte[] keyID = generateUnusedKeyID(); generateUniqueNamedKeyNative(token, alg, keyID, keySize, nickname); return keyID; } /** * @param keySize Key length in bytes. * @param nickname the name of the symmetric key. Duplicate keynames * will be checked for, and are not allowed. */ private native void generateUniqueNamedKeyNative(CryptoToken token, KeyGenAlgorithm alg, byte[] keyID, int keySize, String nickname); /** * Generates a key ID that is currently unused on this token. * The caller is responsible for synchronization issues that may arise * if keys are generated by different threads. */ private byte[] generateUnusedKeyID() throws TokenException { try { SecureRandom rng = SecureRandom.getInstance(RNG_ALG, RNG_PROVIDER); byte[] keyID = new byte[KEYID_LEN]; do { rng.nextBytes(keyID); } while( keyExists(keyID) ); return keyID; } catch(NoSuchAlgorithmException nsae) { throw new RuntimeException("No such algorithm: " + RNG_ALG); } catch(NoSuchProviderException nspe) { throw new RuntimeException("No such provider: " + RNG_PROVIDER); } } private boolean keyExists(byte[] keyid) throws TokenException { return (lookupKey(Encryptor.DEFAULT_ENCRYPTION_ALG, keyid) != null); } /** * Looks up the key on this token with the given algorithm and key ID. * @param alg The algorithm that this key will be used for. * This is necessary because it will be stored along with the * key for later use by the security library. It should match * the actual algorithm of the key you are looking for. If you * pass in a different algorithm and try to use the key that is returned, * the results are undefined. * @return The key, or null if the key is not found. */ public SecretKey lookupKey(EncryptionAlgorithm alg, byte[] keyid) throws TokenException { if( alg == null || keyid == null ) { throw new NullPointerException(); } SymmetricKey k = lookupKeyNative(token, alg, keyid); if( k == null ) { return null; } else { return new SecretKeyFacade(k); } } private native SymmetricKey lookupKeyNative(CryptoToken token, EncryptionAlgorithm alg, byte[] keyid) throws TokenException; public boolean uniqueNamedKeyExists(String nickname) throws TokenException { return (lookupUniqueNamedKey(Encryptor.DEFAULT_ENCRYPTION_ALG, nickname) != null); } /** * Looks up the key on this token with the given algorithm and nickname. * @param alg The algorithm that this key will be used for. * This is necessary because it will be stored along with the * key for later use by the security library. It should match * the actual algorithm of the key you are looking for. If you * pass in a different algorithm and try to use the key that is returned, * the results are undefined. * @param nickname the name of the symmetric key. Duplicate keynames * will be checked for, and are not allowed. * @return The key, or null if the key is not found. */ public SecretKey lookupUniqueNamedKey(EncryptionAlgorithm alg, String nickname) throws TokenException { // always strip all preceding/trailing whitespace // from passed-in String parameters if( nickname != null ) { nickname = nickname.trim(); } if( alg == null || nickname == null || nickname.equals("") ) { throw new NullPointerException(); } SymmetricKey k = lookupUniqueNamedKeyNative(token, alg, nickname); if( k == null ) { return null; } else { return new SecretKeyFacade(k); } } private native SymmetricKey lookupUniqueNamedKeyNative(CryptoToken token, EncryptionAlgorithm alg, String nickname) throws TokenException; /** * Deletes the key with the given keyID from this token. * @throws InvalidKeyException If the key does not exist on this token. */ public void deleteKey(byte[] keyID) throws TokenException, InvalidKeyException { deleteKey(lookupKey(Encryptor.DEFAULT_ENCRYPTION_ALG, keyID)); } /** * If it exists, delete the key with the specified nickname from this * token. */ public void deleteUniqueNamedKey(String nickname) throws TokenException, InvalidKeyException { // only delete this symmetric key if it exists if( uniqueNamedKeyExists(nickname) ) { deleteKey(lookupUniqueNamedKey(Encryptor.DEFAULT_ENCRYPTION_ALG, nickname)); } } /** * Deletes this key from this token. * @throws InvalidKeyException If the key does not reside on this token, * or is not a JSS key. */ public void deleteKey(SecretKey key) throws TokenException, InvalidKeyException { if( key == null ) { throw new NullPointerException(); } if( ! (key instanceof SecretKeyFacade) ) { throw new InvalidKeyException("Key must be a JSS key"); } deleteKeyNative(token, ((SecretKeyFacade)key).key); } private native void deleteKeyNative(CryptoToken token, SymmetricKey key) throws TokenException; } jss-5.0.0/src/main/java/org/mozilla/jss/SecretDecoderRing/package.html000066400000000000000000000010511412550063600256170ustar00rootroot00000000000000 A facility for encrypting and decrypting small amounts of data with a symmetric key. This is most commonly used for encrypting password files to implement single sign-on.

KeyManager is used to create, lookup, and delete the symmetric keys used for SecretDecoderRing. Encryptor is used to encrypt data. Decryptor is used to decrypt data that was previously encrypted with Encryptor. Encoding and Encoding.Template are used internally, but they were made public because they may occasionally be useful to applications. jss-5.0.0/src/main/java/org/mozilla/jss/UserCertConflictException.java000066400000000000000000000005371412550063600257530ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss; public final class UserCertConflictException extends Exception { private static final long serialVersionUID = 1L; } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/000077500000000000000000000000001412550063600206505ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/asn1/ANY.java000066400000000000000000000226131412550063600221460ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * Represents an ASN.1 ANY value. An ANY is just an arbitrary * ASN.1 value. It can be thought of as the simplest implementation of the * ASN1Value interface. Although they can be created * from scratch (from raw BER), instances of ANY are usually * found after decoding * with a template that has an ANY field. * *

* An ANY supports extracting the BER encoding, or decoding * with a different template. */ public class ANY implements ASN1Value { // The complete encoding of header + contents private byte[] encoded; private Tag tag; /** * Creates an ANY value, which is just a generic ASN.1 value. * This method is provided for efficiency if the tag is already known, * so that we don't have to parse the encoding for it. * * @param tag The tag of this value. It must be the same as the actual tag * contained in the encoding. * @param encoded The complete BER encoding of this value, including * tag, form, length, and contents. */ public ANY(Tag tag, byte[] encoded) { this.encoded = encoded; this.tag = tag; } /** * Creates an ANY value, which is just a generic ASN.1 value. * * @param encoded The complete BER encoding of this value, including * tag, form, length, and contents. * @throws InvalidBERException If there is an invalid BER encoding. */ public ANY(byte[] encoded) throws InvalidBERException { try { this.encoded = encoded; ByteArrayInputStream bis = new ByteArrayInputStream(encoded); ASN1Header head = new ASN1Header(bis); this.tag = head.getTag(); } catch (IOException e) { throw new org.mozilla.jss.util.AssertionException( "IOException while creating ANY: " + e); } } /** * Returns the tag of this value. */ @Override public Tag getTag() { return tag; } /** * Returns the complete encoding of header and contents, as passed into * the constructor or read from a BER input stream. * * @return Encoded header and contents. */ public byte[] getEncoded() { return encoded; } /** * Returns the ASN.1 header from the encoding. * * @return ASN.1 header. * @throws InvalidBERException If there is an invalid BER encoding. * @throws IOException If other error occurred. */ public ASN1Header getHeader() throws InvalidBERException, IOException { if (header == null) { ByteArrayInputStream bis = new ByteArrayInputStream(encoded); header = new ASN1Header(bis); } return header; } private ASN1Header header = null; /** * Strips out the header and returns just the contents octets of the * encoding. */ private byte[] contents = null; public byte[] getContents() throws InvalidBERException { try { if (contents == null) { ByteArrayInputStream bis = new ByteArrayInputStream(encoded); header = new ASN1Header(bis); contents = new byte[bis.available()]; if ((contents.length != header.getContentLength()) && (header.getContentLength() != -1)) { throw new InvalidBERException("Length of contents was not the " + "same as the header predicted"); } ASN1Util.readFully(contents, bis); } return contents; } catch (IOException e) { throw new RuntimeException("Unable to read byte array: " + e.getMessage(), e); } } @Override public void encode(OutputStream ostream) throws IOException { ostream.write(encoded); } /** * Decodes this ANY using the given template. This is useful if you * originally decoded something as an ANY because you didn't know * what it was, but now you know what it is supposed to be. * * @param template The template to use to decode this ANY. * @return The output of the given template when it is fed the * encoding of this ANY. * @throws InvalidBERException If there is an invalid BER encoding. */ public ASN1Value decodeWith(ASN1Template template) throws InvalidBERException { try { ByteArrayInputStream bis = new ByteArrayInputStream(encoded); return template.decode(bis); } catch (IOException e) { throw new RuntimeException("Unable to read byte array: " + e.getMessage(), e); } } /** * Decodes this ANY using the given template. This is useful if you * originally decoded something as an ANY because you didn't know * what it was, but now you know what it is supposed to be. * * @param implicitTag The implicit tag for the encoding. * @param template The template to use to decode this ANY. * @return The output of the given template when it is fed the * encoding of this ANY. * @throws InvalidBERException If there is an invalid BER encoding. * @throws IOException If other error occurred. */ public ASN1Value decodeWith(Tag implicitTag, ASN1Template template) throws IOException, InvalidBERException { ByteArrayInputStream bis = new ByteArrayInputStream(encoded); return template.decode(implicitTag, bis); } /** * @param implicitTag This parameter is ignored, because * ANY values cannot have implicit tags. * @throws IOException If an error occurred. */ @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { if (!implicitTag.equals(tag)) { throw new RuntimeException("No implicit tags allowed for ANY"); } ostream.write(encoded); } /** * Extracts the contents from the ANY and encodes them with * the provided tag. * * @param alternateTag Alternate tag. * @param ostream Output stream. * @throws InvalidBERException If there is an invalid BER encoding. * @throws IOException If other error occurred. */ public void encodeWithAlternateTag(Tag alternateTag, OutputStream ostream) throws IOException, InvalidBERException { byte[] contents = getContents(); ASN1Header oldHead = getHeader(); assert (contents.length == oldHead.getContentLength()); ASN1Header newHead = new ASN1Header(alternateTag, oldHead.getForm(), contents.length); newHead.encode(ostream); ostream.write(contents); } /** * Returns a singleton instance of a decoding template. * * @return Decoding template. */ public static Template getTemplate() { return templateInstance; } private static Template templateInstance = new Template(); /** * A class for decoding ANY values from BER. */ public static class Template implements ASN1Template { @Override public boolean tagMatch(Tag tag) { return true; // wheeeeee...it's ANY! } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { try { ASN1Header head = ASN1Header.lookAhead(istream); if (head.getContentLength() == -1) { // indefinite length encoding ByteArrayOutputStream recording = new ByteArrayOutputStream(); // eat the header off the input stream head = new ASN1Header(istream); // write the header to the recording stream recording.write(head.encode()); // write all objects from the input stream to the recording // stream, until we hit an END-OF-CONTENTS tag ANY any; ANY.Template anyt = new ANY.Template(); int count = 0; do { any = (ANY) anyt.decode(istream); recording.write(any.getEncoded()); } while (!any.getTag().equals(Tag.EOC)); return new ANY(head.getTag(), recording.toByteArray()); } else { // definite length encoding byte[] data = new byte[(int) head.getTotalLength()]; ASN1Util.readFully(data, istream); return new ANY(head.getTag(), data); } } catch (InvalidBERException e) { throw new InvalidBERException(e, "ANY"); } } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { throw new InvalidBERException("Implicit tag on ANY"); } } // End of Template } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/ASN1Header.java000066400000000000000000000305211412550063600233270ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigInteger; import java.util.Vector; /** * The portion of a BER encoding that precedes the contents octets. Consists * of the tag, form, and length octets. */ public class ASN1Header { // This is set by the the decoding constructor, and by the encode() // method. If it is set by the decoding constructor, it is supposed // to represent what was actually read from the input stream, so it // must not be overwritten later by the output of encode(), which could // be a different encoding (DER vs. BER, for example). private byte[] cachedEncoding = null; /** * Returns the length of the header plus the length of the contents; * the total length of the DER encoding of an ASN1 value. Returns * -1 if indefinite length encoding was used. * * @return Total length. */ public long getTotalLength() { if (contentLength == -1) { return -1; } else { return encode().length + contentLength; } } private Tag tag; public Tag getTag() { return tag; } // -1 means indefinite length encoding private long contentLength; /** * Returns -1 for indefinite length encoding. * * @return Content length. */ public long getContentLength() { return contentLength; } // PRIMITIVE or CONSTRUCTED public static final Form PRIMITIVE = Form.PRIMITIVE; public static final Form CONSTRUCTED = Form.CONSTRUCTED; private Form form; /** * Returns the Form, PRIMITIVE or CONSTRUCTED. * * @return The form. */ public Form getForm() { return form; } // This is the maximum size of ASN1 Header we support. // 32 bytes is pretty huge, I've never seen anything bigger than 7. private static final int MAX_LOOK_AHEAD = 32; /** * Returns information about the next item in the stream, but does not * consume any octets. * * @param derStream DER stream. * @return ASN.1 header. * @throws InvalidBERException If there is an invalid BER encoding. * @exception IOException If the input stream does not support look ahead. */ public static ASN1Header lookAhead(InputStream derStream) throws IOException, InvalidBERException { if (!derStream.markSupported()) { throw new IOException("Mark not supported on this input stream"); } derStream.mark(MAX_LOOK_AHEAD); ASN1Header info = new ASN1Header(derStream); derStream.reset(); return info; } /** * Gets info about the next item in the DER stream, consuming the * identifier and length octets. * * @param istream Input stream. * @throws InvalidBERException If there is an invalid BER encoding. * @throws IOException If other error occurred. */ public ASN1Header(InputStream istream) throws InvalidBERException, IOException { // default BAOS size is 32 bytes, which is plenty ByteArrayOutputStream encoding = new ByteArrayOutputStream(); int inInt = istream.read(); if (inInt == -1) { throw new InvalidBERException("End-of-file reached while " + "decoding ASN.1 header"); } encoding.write(inInt); byte byte1 = (byte) inInt; Tag.Class tagClass; // // Get Tag Class // tagClass = Tag.Class.fromInt((byte1 & 0xff) >>> 6); // // Get form // if ((byte1 & 0x20) == 0x20) { form = CONSTRUCTED; } else { form = PRIMITIVE; } // // Get Tag Number // long tagNum; if ((byte1 & 0x1f) == 0x1f) { // long form // // read all octets into a Vector of Bytes // byte next; Vector bV = new Vector<>(); // last byte has MSB == 0. do { inInt = istream.read(); if (inInt == -1) { throw new InvalidBERException("End-of-file reached while" + " decoding ASN.1 header"); } encoding.write(inInt); next = (byte) inInt; bV.addElement(Byte.valueOf(next)); } while ((next & 0x80) == 0x80); assert (bV.size() > 0); // // Copy Vector of 7-bit bytes into array of 8-bit bytes. // byte[] bA = new byte[((bV.size() * 7) + 7) / 8]; int v; // vector index int a; // array index // clear the target array for (a = 0; a < bA.length; a++) { bA[a] = 0; } int shift = 0; // the amount the Vector is shifted from the array // copy bits from the Vector to the array, going from the // end (LSB) to the beginning (MSB). a = bA.length - 1; for (v = bV.size() - 1; v >= 0; v--) { assert (v >= 0); assert (v < bV.size()); assert (a >= 0); assert (a < bA.length); // MSB is not part of the number byte b = (byte) (bV.elementAt(v).byteValue() & 0x7f); bA[a] |= b << shift; if (shift > 1) { // The byte from the Vector falls across a byte boundary // in the array. We've already got the less-significant // bits, now copy the more-significant bits into // the next element of the array. assert (a > 0); --a; bA[a] |= b >>> (8 - shift); } shift = (shift + 7) % 8; // update shift } // Create a new unsigned BigInteger from the byte array tagNum = (new BigInteger(1, bA)).longValue(); } else { // short form tagNum = byte1 & 0x1f; } tag = new Tag(tagClass, tagNum); // // Get Length // inInt = istream.read(); if (inInt == -1) { throw new InvalidBERException("End-of-file reached while " + "decoding ASN.1 header"); } encoding.write(inInt); byte lenByte = (byte) inInt; if ((lenByte & 0x80) == 0) { // short form contentLength = lenByte; } else { // long form if ((lenByte & 0x7f) == 0) { // indefinite contentLength = -1; } else { // definite byte[] lenBytes = new byte[lenByte & 0x7f]; ASN1Util.readFully(lenBytes, istream); encoding.write(lenBytes); contentLength = (new BigInteger(1, lenBytes)).longValue(); } } // save our encoding so we don't have to recompute it later cachedEncoding = encoding.toByteArray(); } /** * This constructor is to be called when we are constructing an ASN1Value * rather than decoding it. * * @param tag Tag. * @param form Form. * @param contentLength Must be ≥0. Although indefinite length * decoding is supported, indefinite length encoding * is not. */ public ASN1Header(Tag tag, Form form, long contentLength) { this.tag = tag; this.form = form; assert (contentLength >= 0); this.contentLength = contentLength; } public void encode(OutputStream ostream) throws IOException { ostream.write(encode()); } public byte[] encode() { // It's important that we not recompute the encoding if it was // set by ASN1Header(InputStream), since in that case it represents // the encoding that was actually read from the InputStream. if (cachedEncoding != null) { return cachedEncoding; } ByteArrayOutputStream cache = new ByteArrayOutputStream(); // // Identifier octet(s) // byte idOctet = 0; idOctet |= tag.getTagClass().toInt() << 6; if (form == CONSTRUCTED) { idOctet |= 0x20; } if (tag.getNum() <= 30) { // short form idOctet |= (tag.getNum() & 0x1f); cache.write(idOctet); } else { // long form idOctet |= 0x1f; BigInteger tagNum = BigInteger.valueOf(tag.getNum()); cache.write(idOctet); int bitlength = tagNum.bitLength(); int reps = (bitlength + 6) / 7; for (reps = reps - 1; reps > 0; reps--) { long shifted = tag.getNum() >>> (7 * reps); cache.write((((byte) shifted) & 0x7f) | 0x80); } cache.write(((byte) tag.getNum()) & 0x7f); } // // Length Octets // if (contentLength == -1) { // indefinite form cache.write((byte) 0x80); } else if (contentLength <= 127) { // short form cache.write((byte) contentLength); } else { // long form byte[] val = unsignedBigIntToByteArray( BigInteger.valueOf(contentLength)); cache.write(((byte) val.length) | 0x80); cache.write(val, 0, val.length); } cachedEncoding = cache.toByteArray(); return cachedEncoding; } /** * Converts an unsigned BigInteger to a minimal-length byte array. * This is necessary because BigInteger.toByteArray() attaches an extra * sign bit, which could cause the size of the byte representation to * be bumped up by an extra byte. * * @param bi Input BigInteger. * @return Byte array. */ public static byte[] unsignedBigIntToByteArray(BigInteger bi) { // make sure it is not negative assert (bi.compareTo(BigInteger.valueOf(0)) != -1); // find minimal number of bytes to hold this value int bitlen = bi.bitLength(); // minimal number of bits, without sign int bytelen; if (bitlen == 0) { // special case, since bitLength() returns 0 bytelen = 1; } else { bytelen = (bitlen + 7) / 8; } byte[] withSign = bi.toByteArray(); if (bytelen == withSign.length) { return withSign; } else { // trim off extra byte at the beginning assert (bytelen == withSign.length - 1); assert (withSign[0] == 0); byte[] without = new byte[bytelen]; System.arraycopy(withSign, 1, without, 0, bytelen); return without; } } /** * Verifies that this header has the given tag and form. * * @param expectedTag Expected tag. * @param expectedForm Expected form. * @exception InvalidBERException If the header's tag or form * differ from those passed in. */ public void validate(Tag expectedTag, Form expectedForm) throws InvalidBERException { validate(expectedTag); if (getForm() != expectedForm) { throw new InvalidBERException("Incorrect form: expected [" + expectedForm + "], found [" + getForm()); } } /** * Verifies that this head has the given tag. * * @param expectedTag Expected tag. * @exception InvalidBERException If the header's tag differs from that * passed in. */ public void validate(Tag expectedTag) throws InvalidBERException { if (!getTag().equals(expectedTag)) { throw new InvalidBERException("Incorrect tag: expected [" + expectedTag + "], found [" + getTag() + "]"); } } /** * @return true if this is a BER end-of-contents marker. */ public boolean isEOC() { return (tag.equals(Tag.EOC)); } } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/ASN1Template.java000066400000000000000000000040321412550063600237100ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.IOException; import java.io.InputStream; /** * An interface for decoding ASN1Values from their BER encodings. * * @see ASN1Value */ public interface ASN1Template { /** * Determines whether the given tag will satisfy this template. * * @param tag Tag. * @return True if the given tag will satisfy this template. */ public boolean tagMatch(Tag tag); /** * Decodes an ASN1Value from the InputStream without an implicit tag. * * @param istream Must support marking (markSupported() == true). * For example, ByteArrayInputStream and BufferedInputStream * support marking, but FileInputStream does not. If your source * does not support marking, you can wrap it in a * BufferedInputStream. * @return ASN.1 value. * @throws InvalidBERException If there is an invalid BER encoding. * @throws IOException If other error occurred. */ public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException; /** * Decodes an ASN1Value from the InputStream with the given implicit * tag. * * @param implicitTag Implicit tag. * @param istream Must support marking (markSupported() == true). * For example, ByteArrayInputStream and BufferedInputStream * support marking, but FileInputStream does not. If your source * does not support marking, you can wrap it in a * BufferedInputStream. * @return ASN.1 value. * @throws InvalidBERException If there is an invalid BER encoding. * @throws IOException If other error occurred. */ public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException; } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/ASN1Util.c000066400000000000000000000066111412550063600223600ustar00rootroot00000000000000/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * 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 Services for Java. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "_jni/org_mozilla_jss_asn1_ASN1Util.h" #include #include #include #include #include #include #include #include #include /*********************************************************************** * * Java_org_mozilla_jss_asn1_ASN1Util_getTagDescriptionByOid * retrieves OID description by NSS's OID Tag identifier * the OID byte array is expected to be without the OID Tag (6) and size * (together 2 bytes) */ JNIEXPORT jstring JNICALL Java_org_mozilla_jss_asn1_ASN1Util_getTagDescriptionByOid(JNIEnv *env, jobject this, jbyteArray oidBA) { SECItem *oid = NULL; SECOidTag oidTag = SEC_OID_UNKNOWN; const char *oidDesc = NULL; jstring description = (jstring) ""; if (oidBA == NULL) { JSS_throwMsg(env, INVALID_PARAMETER_EXCEPTION, "JSS getTagDescriptionByOid: oidBA null"); goto finish; } else { /************************************************** * Setup the parameters *************************************************/ oid = JSS_ByteArrayToSECItem(env, oidBA); if (oid == NULL) { JSS_throwMsg(env, INVALID_PARAMETER_EXCEPTION, "JSS getTagDescriptionByOid: JSS_ByteArrayToSECItem failed"); goto finish; } /* * SECOID_FindOIDTag() returns SEC_OID_UNKNOWN if no match */ oidTag = SECOID_FindOIDTag(oid); if (oidTag == SEC_OID_UNKNOWN) { JSS_throwMsg(env, INVALID_PARAMETER_EXCEPTION, "JSS getTagDescriptionByOid: OID UNKNOWN"); goto finish; } oidDesc = SECOID_FindOIDTagDescription(oidTag); if (oidDesc == NULL) { oidDesc = ""; } description = (*env)->NewStringUTF(env, oidDesc); } finish: return description; } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/ASN1Util.java000066400000000000000000000121441412550063600230550ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; public class ASN1Util { public static byte[] encode(ASN1Value val) { return encode(val.getTag(), val); } public static byte[] encode(Tag implicitTag, ASN1Value val) { try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); val.encode(implicitTag, bos); return bos.toByteArray(); } catch (IOException e) { throw new RuntimeException("Unable to encode byte array: " + e.getMessage(), e); } } public static ASN1Value decode(ASN1Template template, byte[] encoded) throws InvalidBERException { try { ByteArrayInputStream bis = new ByteArrayInputStream(encoded); return template.decode(bis); } catch (IOException e) { throw (InvalidBERException) new InvalidBERException("Unable to decode byte array: " + e.getMessage()) .initCause(e); } } public static ASN1Value decode(Tag implicitTag, ASN1Template template, byte[] encoded) throws InvalidBERException { try { ByteArrayInputStream bis = new ByteArrayInputStream(encoded); return template.decode(implicitTag, bis); } catch (IOException e) { throw (InvalidBERException) new InvalidBERException("Unable to decode byte array: " + e.getMessage()) .initCause(e); } } /** * Fills a byte array with bytes from an input stream. This method * keeps reading until the array is filled, an IOException occurs, or EOF * is reached. The byte array will be completely filled unless an * exception is thrown. * * @param bytes A byte array which will be filled up. * @param istream The input stream from which to read the bytes. * @exception IOException If an IOException occurs reading from the * stream, or EOF is reached before the byte array is filled. */ public static void readFully(byte[] bytes, InputStream istream) throws IOException { int numRead = 0; while (numRead < bytes.length) { int nr = istream.read(bytes, numRead, bytes.length - numRead); if (nr == -1) { throw new EOFException(); } numRead += nr; } } /** * returns the ECC curve byte array given the X509 public key byte array * * @param X509PubKeyBytes byte array of an X509PubKey * @param withHeader tells if the return byes should inclulde the tag and size header or not * @return ECC curve byte array. */ public static byte[] getECCurveBytesByX509PublicKeyBytes(byte[] X509PubKeyBytes, boolean withHeader) throws IllegalArgumentException, ArrayIndexOutOfBoundsException, NullPointerException { if ((X509PubKeyBytes == null) || (X509PubKeyBytes.length == 0)) { throw new IllegalArgumentException("X509PubKeyBytes null"); } /* EC public key OID complete with tag and size */ byte[] EC_PubOIDBytes_full = ASN1Util.encode(OBJECT_IDENTIFIER.EC_PUBKEY_OID); /* EC public key OID without tag and size */ byte[] EC_PubOIDBytes = Arrays.copyOfRange(EC_PubOIDBytes_full, 2, EC_PubOIDBytes_full.length); int curveBeginIndex = 0; for (int idx = 0; idx <= X509PubKeyBytes.length; idx++) { byte[] tmp = Arrays.copyOfRange(X509PubKeyBytes, idx, idx + EC_PubOIDBytes.length); if (Arrays.equals(tmp, EC_PubOIDBytes)) { curveBeginIndex = idx + EC_PubOIDBytes.length; break; } } int curveByteArraySize = X509PubKeyBytes[curveBeginIndex + 1]; if (withHeader) { /* actual curve with tag and size */ byte curve[] = Arrays.copyOfRange(X509PubKeyBytes, curveBeginIndex, curveBeginIndex + curveByteArraySize + 2); return curve; } else { /* actual curve without tag and size */ byte curve[] = Arrays.copyOfRange(X509PubKeyBytes, curveBeginIndex + 2, curveBeginIndex + 2 + curveByteArraySize); return curve; } } /** * getOIDdescription() returns a text description of the OID * from OID byte array * the OID byte array is expected to be without the OID Tag (6) and size * (together 2 bytes) * * @param oidBA OID byte array. * @return OID description. */ public static String getOIDdescription(byte[] oidBA) { return getTagDescriptionByOid(oidBA); } /** * get OID description JNI method */ private native static String getTagDescriptionByOid(byte[] oidBA); } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/ASN1Value.java000066400000000000000000000022631412550063600232150ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.IOException; import java.io.OutputStream; /** * A value that can be decoded from BER and encoded to DER. * * @see ASN1Template */ public interface ASN1Value { /** * Returns the base tag for this type, not counting any tags * that may be imposed on it by its context. * * @return Base tag. */ public Tag getTag(); /** * Write this value's DER encoding to an output stream using * its own base tag. * * @param ostream Output stream. * @throws IOException If an error occurred. */ public void encode(OutputStream ostream) throws IOException; /** * Write this value's DER encoding to an output stream using * an implicit tag. * * @param implicitTag Implicit tag. * @param ostream Output stream. * @throws IOException If an error occurred. */ public void encode(Tag implicitTag, OutputStream ostream) throws IOException; } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/BIT_STRING.java000066400000000000000000000243071412550063600232250ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.BitSet; /** * An ASN.1 BIT STRING, which is an ordered sequence of bits. * The bits are stored the same way they are encoded in BER: as an array * of bytes with 0-7 unused bits at the end. */ public class BIT_STRING implements ASN1Value { private byte[] bits; private int padCount; private boolean removeTrailingZeroes = false; /** * @param bits The bits packed into an array of bytes, with padding * at the end. The array may be empty (but not null), in which case * padCount must be zero. The array is referenced, * not cloned. * @param padCount The number of padding bits at the end of the array. * Must be in the range [0,7]. * @exception NumberFormatException If padCount is not in * the range [0,7], or bits is * empty and padCount is non-zero. */ public BIT_STRING(byte[] bits, int padCount) throws NumberFormatException { if (padCount < 0 || padCount > 7) { throw new NumberFormatException(); } if (bits.length == 0 && padCount != 0) { throw new NumberFormatException(); } this.bits = bits; this.padCount = padCount; } /** * Constructs a BIT_STRING from a BitSet. * * @param bs A BitSet. * @param numBits The number of bits to copy from the BitSet. * This is necessary because the size of a BitSet is always padded * up to a multiple of 64, but not all of these bits may * be significant. * @exception NumberFormatException If numBits is larger * than bs.size() or less than zero. */ public BIT_STRING(BitSet bs, int numBits) throws NumberFormatException { if (numBits < 0 || numBits > bs.size()) { throw new NumberFormatException(); } // allocate enough bytes to hold all the bits bits = new byte[(numBits + 7) / 8]; padCount = (bits.length * 8) - numBits; assert (padCount >= 0 && padCount <= 7); for (int i = 0; i < numBits; i++) { if (bs.get(i)) { bits[i / 8] |= 0x80 >>> (i % 8); } } } /** * Determines whether the DER-encoding of this bitstring will have * its trailing zeroes removed. Generally, DER requires that trailing * zeroes be removed when the bitstring is used to hold flags, but * not when it is used to hold binary data (such as a public key). * The default is false. * * @return True if trailing zeroes are to be removed. */ public boolean getRemoveTrailingZeroes() { return this.removeTrailingZeroes; } /** * Determines whether the DER-encoding of this bitstring will have * its trailing zeroes removed. Generally, DER requires that trailing * zeroes be removed when the bitstring is used to hold flags, but * not when it is used to hold binary data (such as a public key). * The default is false. If this bit string is used to hold * flags, you should set this to true. * * @param removeTrailingZeroes True if trailing zeroes are to be removed. */ public void setRemoveTrailingZeroes(boolean removeTrailingZeroes) { this.removeTrailingZeroes = removeTrailingZeroes; } /** * Returns the bits packed into an array of bytes, with padding * at the end. The array may be empty (but not null), in which case * padCount must be zero. The array is referenced, * not cloned. * * @return BIT STRING as byte array. */ public byte[] getBits() { return bits; } /** * Copies this BIT STRING into a Java BitSet. Note that BitSet.size() * will not accurately reflect the number of bits in the BIT STRING, * because the size of a BitSet is always rounded up to the next multiple * of 64. The extra bits will be set to 0. * * @return BIT STRING as BitSet. */ public BitSet toBitSet() { BitSet bs = new BitSet(); int numBits = (bits.length * 8) - padCount; for (int i = 0; i < numBits; i++) { if ((bits[i / 8] & (0x80 >>> (i % 8))) != 0) { bs.set(i); } else { bs.clear(i); } } return bs; } /** * Copies this BIT STRING into a boolean array. Each element of the array * represents one bit with true for 1 and false * for 0. * * @return BIT STRING as boolean array. */ public boolean[] toBooleanArray() { boolean[] array = new boolean[(bits.length * 8) - padCount]; // all elements are set to false by default for (int i = 0; i < array.length; i++) { if ((bits[i / 8] & (0x80 >>> (i % 8))) != 0) { array[i] = true; } } return array; } /** * Returns the number of padding bits at the end of the array. * Must be in the range [0,7]. * * @return Number of padding. */ public int getPadCount() { return padCount; } public static final Tag TAG = new Tag(Tag.UNIVERSAL, 3); public static final Form FORM = Form.PRIMITIVE; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { // force all unused bits to be zero, in support of DER standard. if (bits.length > 0) { bits[bits.length - 1] &= (0xff << padCount); } int padBits; int numBytes; if (removeTrailingZeroes) { // first pare off empty bytes numBytes = bits.length; for (; numBytes > 0; --numBytes) { if (bits[numBytes - 1] != 0) { break; } } // Now compute the number of unused bits. This includes any // trailing zeroes, whether they are significant or not. if (numBytes == 0) { padBits = 0; } else { for (padBits = 0; padBits < 8; ++padBits) { if ((bits[numBytes - 1] & (1 << padBits)) != 0) { break; } } assert (padBits >= 0 && padBits <= 7); } } else { // Don't remove trailing zeroes. Just write the bits out as-is. padBits = padCount; numBytes = bits.length; } ASN1Header head = new ASN1Header(implicitTag, FORM, numBytes + 1); head.encode(ostream); ostream.write(padBits); ostream.write(bits, 0, numBytes); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A class for decoding a BIT_STRING from its BER encoding. */ public static class Template implements ASN1Template { @Override public boolean tagMatch(Tag tag) { return (TAG.equals(tag)); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { try { ASN1Header head = new ASN1Header(istream); head.validate(implicitTag); if (head.getContentLength() == -1) { // indefinite length encoding ByteArrayOutputStream bos = new ByteArrayOutputStream(); int padCount = 0; ASN1Header ahead; do { ahead = ASN1Header.lookAhead(istream); if (!ahead.isEOC()) { if (padCount != 0) { throw new InvalidBERException("Element of constructed " + "BIT STRING has nonzero unused bits, but is not\n" + "the last element of the construction."); } BIT_STRING.Template bst = new BIT_STRING.Template(); BIT_STRING bs = (BIT_STRING) bst.decode(istream); bos.write(bs.getBits()); padCount = bs.getPadCount(); } } while (!ahead.isEOC()); // consume the EOC ahead = new ASN1Header(istream); return new BIT_STRING(bos.toByteArray(), padCount); } // First octet is the number of unused bits in last octet int padCount = istream.read(); if (padCount == -1) { throw new InvalidBERException.EOF(); } else if (padCount < 0 || padCount > 7) { throw new InvalidBERException("Unused bits not in range [0,7]"); } // get the rest of the octets byte[] bits = new byte[(int) head.getContentLength() - 1]; ASN1Util.readFully(bits, istream); return new BIT_STRING(bits, padCount); } catch (InvalidBERException e) { throw new InvalidBERException(e, "BIT STRING"); } } } // end of Template } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/BMPString.java000066400000000000000000000073551412550063600233320ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.CharConversionException; import java.io.UnsupportedEncodingException; /** * The ASN.1 type BMPString. BMPStrings use the Unicode character set. * They are encoded and decoded in big-endian format using two octets. */ public class BMPString extends CharacterString { /** * Creates a new BMPString from an array of Java characters. * * @param chars Input characters. * @throws CharConversionException If an error occurred. */ public BMPString(char[] chars) throws CharConversionException { super(chars); } /** * Creates a new BMPString from a Java String. * * @param s Input string. * @throws CharConversionException If an error occurred. */ public BMPString(String s) throws CharConversionException { super(s); } /** * Returns the conversion object for converting between an encoded byte * array an an array of Java characters. * * @return Character converter. */ @Override CharConverter getCharConverter() { return converterInstance; } private static final BMPConverter converterInstance = new BMPConverter(); static final Tag TAG = new Tag(Tag.UNIVERSAL, 30); static final Form FORM = Form.PRIMITIVE; @Override public Tag getTag() { return TAG; } /** * Returns a singleton instance of BMPString.Template. This is more * efficient than creating a new BMPString.Template. * * @return BMSString template. */ public static Template getTemplate() { return templateInstance; } private static final Template templateInstance = new Template(); // nested class public static class Template extends CharacterString.Template { @Override protected Tag getTag() { return TAG; } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override protected CharConverter getCharConverter() { return new BMPConverter(); } @Override protected CharacterString generateInstance(char[] chars) throws CharConversionException { return new BMPString(chars); } @Override protected String typeName() { return "BMPString"; } } private static class BMPConverter implements CharConverter { @Override public char[] byteToChar(byte[] bytes, int offset, int len) throws CharConversionException { try { String s = new String(bytes, offset, len, "UnicodeBig"); return s.toCharArray(); } catch (UnsupportedEncodingException e) { String err = "Unable to find UnicodeBig encoding mechanism"; throw (CharConversionException) new CharConversionException(err).initCause(e); } } @Override public byte[] charToByte(char[] chars, int offset, int len) throws CharConversionException { try { // We don't want the byte-order mark String s = new String(chars, offset, len); return s.getBytes("UnicodeBigUnmarked"); } catch (UnsupportedEncodingException e) { String err = "Unable to find UnicodeBigUnmarked encoding mechanism"; throw (CharConversionException) new CharConversionException(err).initCause(e); } } } // end of char converter } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/BOOLEAN.java000066400000000000000000000057651412550063600226070ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * An ASN.1 BOOLEAN value. */ public class BOOLEAN implements ASN1Value { public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 1); public static final Form FORM = Form.PRIMITIVE; @Override public Tag getTag() { return TAG; } private ASN1Header getHeader(Tag implicitTag) { return new ASN1Header(implicitTag, FORM, 1); } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { getHeader(implicitTag).encode(ostream); if (val) { ostream.write(0xff); } else { ostream.write(0x00); } } private boolean val; /** * Creates a BOOLEAN with the given value. * * @param val Boolean value. */ public BOOLEAN(boolean val) { this.val = val; } /** * @return The boolean value of this BOOLEAN. */ public boolean toBoolean() { return val; } /** * Returns "true" or "false". */ @Override public String toString() { if (val) { return "true"; } else { return "false"; } } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Class for decoding BOOLEAN values from their BER * encodings. */ public static class Template implements ASN1Template { @Override public boolean tagMatch(Tag tag) { return (tag.equals(BOOLEAN.TAG)); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag tag, InputStream istream) throws IOException, InvalidBERException { try { ASN1Header head = new ASN1Header(istream); head.validate(tag, FORM); int b = istream.read(); if (b == -1) { throw new InvalidBERException("End-of-file reached while " + "decoding BOOLEAN"); } if (b == 0x00) { return new BOOLEAN(false); } else { return new BOOLEAN(true); } } catch (InvalidBERException e) { throw new InvalidBERException(e, "BOOLEAN"); } } } } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/CHOICE.java000066400000000000000000000207661412550063600224600ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Vector; /** * Objects of this class are generated by CHOICE.Template.decode(). It is * not necessary to use them to encode a CHOICE. Since the encoding of a * CHOICE is simply the encoding of the chosen element, it is easier * to just write out the chosen element. */ public class CHOICE implements ASN1Value { private Tag tag; private ASN1Value val; /** * Create a CHOICE whose chosen element has an implicit tag. * * @param implicitTag Implicit tag. * @param val The value. */ public CHOICE(Tag implicitTag, ASN1Value val) { tag = implicitTag; this.val = val; } /** * Create a CHOICE whose chosen element has no implicit tag. * * @param val The value. */ public CHOICE(ASN1Value val) { this.tag = val.getTag(); this.val = val; } /** * Returns the tag that the chosen element is encoded with, which is * either the underlying tag of the element or an implicit tag. */ @Override public Tag getTag() { return tag; } /** * @return The chosen value. */ public ASN1Value getValue() { return val; } public static CHOICE.Template getTemplate() { return new CHOICE.Template(); } /** * Encodes this CHOICE. This merely consists of encoding the chosen * element with an implicit tag, if one was given in the constructor, * or with its own underlying tag. */ @Override public void encode(OutputStream ostream) throws IOException { val.encode(tag, ostream); } /** * Encodes this CHOICE. This merely consists of encoding the chosen * element with an implicit tag, if one was given in the constructor, * or with its own underlying tag. * * @param implicitTag This value is ignored. The tag of a CHOICE * is merely the tag of the chosen element of the CHOICE. A * CHOICE cannot itself have an implicit tag. */ @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { assert (implicitTag.equals(tag)); val.encode(tag, ostream); } /** * A Template for decoding ASN.1 CHOICEs */ public static class Template implements ASN1Template { // The the various possibilities in this CHOICE private Vector templates = new Vector<>(); /** * Creates an empty CHOICE template */ public Template() { } /** * Adds a new sub-template to this CHOICE template with no implicit tag. * * @param template Sub-template. */ public void addElement(ASN1Template template) { templates.addElement(new Element(template)); } /** * Adds a new sub-template to this CHOICE template with an implicit tag. * * @param implicitTag Implicit tag. * @param template Sub-template. */ public void addElement(Tag implicitTag, ASN1Template template) { templates.addElement(new Element(implicitTag, template)); } /** * @return The number of elements in this CHOICE template. */ public int size() { return templates.size(); } /** * @param index Element index. * @return The element at the specified index. */ public ASN1Template elementAt(int index) { return templates.elementAt(index).getTemplate(); } /** * Retrieves the implicit tag of the element at the specified index. * Returns null if there is no implicit tag for this element. * * @param index Element index. * @return The implicit tag. */ public Tag implicitTagAt(int index) { return templates.elementAt(index).getImplicitTag(); } /** * Empties this CHOICE template. */ public void removeAllElements() { templates.removeAllElements(); } /** * Removes the element at the specified index. * * @param index Element index. */ public void removeElementAt(int index) { templates.removeElementAt(index); } /** * Determines whether the given tag will satisfy this template. * * @param t The tag. * @return True if the tag satisfies any sub-template. */ @Override public boolean tagMatch(Tag t) { int size = size(); for (int i = 0; i < size; i++) { Tag impl = implicitTagAt(i); if (impl != null) { // There is an implicit tag, if we match it we have a match if (impl.equals(t)) { return true; } } else { // no implicit tag, look at the sub-template itself ASN1Template templ = elementAt(i); if (templ.tagMatch(t)) { return true; } } } // none of the elements matched return false; } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { ASN1Header head = ASN1Header.lookAhead(istream); Tag tag = head.getTag(); // Loop over all the elements of the CHOICE template until we // find one with a matching tag. int size = size(); for (int i = 0; i < size; i++) { if (implicitTagAt(i) != null) { if (implicitTagAt(i).equals(tag)) { // match by implicit tag! ASN1Value val = elementAt(i).decode(implicitTagAt(i), istream); //return elementAt(i).decode( implicitTagAt(i), istream ); return new CHOICE(implicitTagAt(i), val); } } else { if (elementAt(i).tagMatch(tag)) { // match by base tag ! //return elementAt(i).decode(istream); return new CHOICE(elementAt(i).decode(istream)); } } } // we didn't find any match throw new InvalidBERException("Unable to decode CHOICE"); } // Implicit tags are illegal for CHOICE (and ANY) /** * Decodes a CHOICE. * * @param implicitTag This parameter is ignored. A choice * cannot have an implicit tag. */ @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { return decode(istream); } /** * An element in a CHOICE template, consisting of a nested template * and, optionally, an implicit tag for that template. */ private static class Element { private ASN1Template template; private Tag implicitTag = null; /** * Creates a CHOICE template element with no implicit tag. */ public Element(ASN1Template template) { this.template = template; } /** * Creates a CHOICE template element with an implicit tag. */ public Element(Tag implicitTag, ASN1Template template) { this.template = template; this.implicitTag = implicitTag; } /** * Returns the template of this CHOICE template element. */ public ASN1Template getTemplate() { return template; } /** * Returns the implicit tag for this CHOICE template element, * if there is one. If not, returns null. */ public Tag getImplicitTag() { return implicitTag; } } } } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/CharConverter.java000066400000000000000000000010141412550063600242540ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.CharConversionException; interface CharConverter { public char[] byteToChar(byte[] bytes, int offset, int len) throws CharConversionException; public byte[] charToByte(char[] chars, int offset, int len) throws CharConversionException; } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/CharacterString.java000066400000000000000000000123141412550063600245770ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.ByteArrayOutputStream; import java.io.CharConversionException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * An abstract base class for all character string types in ASN.1. */ public abstract class CharacterString implements ASN1Value { abstract CharConverter getCharConverter(); @Override public abstract Tag getTag(); static final Form FORM = Form.PRIMITIVE; private char[] chars; /** * Converts this ASN.1 character string to a Java String. * * @return ASN.1 character string as String. */ @Override public String toString() { return new String(chars); } /** * Converts this ASN.1 character string to an array of Java characters. * * @return ASN.1 character string as character array. */ public char[] toCharArray() { return chars; } protected CharacterString(char[] chars) throws CharConversionException { this.chars = chars; cachedContents = computeContents(); } protected CharacterString(String s) throws CharConversionException { this.chars = s.toCharArray(); cachedContents = computeContents(); } private byte[] cachedContents; private byte[] getEncodedContents() { return cachedContents; } private byte[] computeContents() throws CharConversionException { CharConverter converter = getCharConverter(); byte[] contents = converter.charToByte(chars, 0, chars.length); return contents; } @Override public void encode(OutputStream ostream) throws IOException { encode(getTag(), ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { byte[] contents = getEncodedContents(); ASN1Header head = new ASN1Header(implicitTag, FORM, contents.length); head.encode(ostream); ostream.write(contents); } public abstract static class Template implements ASN1Template { /** * Must be overridden to return the tag for the subclass. * * @return Tag. */ protected abstract Tag getTag(); @Override public abstract boolean tagMatch(Tag tag); /** * Must be overridden to return the correct character converter * for the subclass. * * @return Character converter. */ protected abstract CharConverter getCharConverter(); /** * Must be overridden to create an instance of the subclass given * a char array. * * @param chars Input characters. * @return Character string. * @throws CharConversionException If an error occurred. */ protected abstract CharacterString generateInstance(char[] chars) throws CharConversionException; /** * Must be overridden to provide the name of the subclass, for including * into error messages. * * @return Name of the subclass. */ protected abstract String typeName(); @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(getTag(), istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { try { ASN1Header head = new ASN1Header(istream); head.validate(implicitTag); byte[] raw; // raw bytes, not translated to chars yet if (head.getContentLength() == -1) { // indefinite length encoding ASN1Header ahead; ByteArrayOutputStream bos = new ByteArrayOutputStream(); do { ahead = ASN1Header.lookAhead(istream); if (!ahead.isEOC()) { OCTET_STRING.Template ot = new OCTET_STRING.Template(); OCTET_STRING os = (OCTET_STRING) ot.decode(istream); bos.write(os.toByteArray()); } } while (!ahead.isEOC()); // consume EOC ahead = new ASN1Header(istream); raw = bos.toByteArray(); } else { // definite length raw = new byte[(int) head.getContentLength()]; ASN1Util.readFully(raw, istream); } char[] chars = getCharConverter().byteToChar(raw, 0, raw.length); return generateInstance(chars); } catch (CharConversionException e) { throw new InvalidBERException(e.getMessage()); } catch (InvalidBERException e) { throw new InvalidBERException(e, typeName()); } } } } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/CountingStream.java000066400000000000000000000054221412550063600244600ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.IOException; import java.io.InputStream; /** * This class keeps track of the number of bytes that have been read from * a stream. It will be incremented by the number of bytes read or skipped. * If the stream is marked and then reset, the number of bytes read will * be reset as well. */ class CountingStream extends InputStream { private int count = 0; private int markpos; private InputStream source; private static final boolean DEBUG = false; public CountingStream(InputStream source) { this.source = source; } @Override public int available() throws IOException { return source.available(); } @Override public void mark(int readlimit) { source.mark(readlimit); markpos = count; if (DEBUG) { System.out.println("Marked at position " + markpos); } } @Override public boolean markSupported() { return source.markSupported(); } @Override public int read() throws IOException { int n = source.read(); if (n != -1) { count++; if (DEBUG) { System.out.println("read() 1 byte, count=" + count); } } return n; } @Override public int read(byte[] buffer) throws IOException { int n = source.read(buffer); if (n != -1) { count += n; } if (DEBUG) { System.out.println("read([]) " + n + " bytes, count=" + count); } return n; } @Override public int read(byte[] buffer, int offset, int count) throws IOException { int n = source.read(buffer, offset, count); if (n != -1) { this.count += n; } if (DEBUG) { System.out.println("read(...) " + n + " bytes, count=" + this.count); } return n; } @Override public void reset() throws IOException { source.reset(); if (DEBUG) { System.out.println("reset from " + count + " to " + markpos); } count = markpos; } @Override public long skip(long count) throws IOException { this.count += count; if (DEBUG) { System.out.println("skipped " + count + ", now at " + this.count); } return source.skip(count); } public int getNumRead() { return count; } public void resetNumRead() { count = 0; markpos = 0; if (DEBUG) { System.out.println("resetting count to 0"); } } } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/ENUMERATED.java000066400000000000000000000046651412550063600231570ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.IOException; import java.io.InputStream; /** * Represents an ASN.1 ENUMERATED value. This has the same * interface as INTEGER */ public class ENUMERATED extends INTEGER { private static final long serialVersionUID = 1L; public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 10); @Override public Tag getTag() { return TAG; } /** * Creates a new ENUMERATED value from a long int. * * @param val Input value. */ public ENUMERATED(long val) { super(val); } ENUMERATED(byte[] valBytes) { super(valBytes); } /** * @return The value as a long int. */ public long getValue() { return longValue(); } private static final ENUMERATED.Template templateInstance = new ENUMERATED.Template(); public static ASN1Template getTemplate() { return templateInstance; } /** * A template for decoding ENUMERATED values from their BER encodings. * The template reads the value as an INTEGER. It does not check that it * is a valid value for the ENUMERATED type. */ public static class Template extends INTEGER.Template { @Override Tag getTag() { return ENUMERATED.TAG; } @Override public boolean tagMatch(Tag tag) { return (tag.equals(ENUMERATED.TAG)); } @Override public ASN1Value decode(Tag tag, InputStream derStream) throws InvalidBERException, IOException { try { ASN1Header wrapper = new ASN1Header(derStream); wrapper.validate(tag, FORM); // Is length < 1 ? if (wrapper.getContentLength() < 1) { throw new InvalidBERException("Invalid 0 length for ENUMERATED"); } byte[] valBytes = new byte[(int) wrapper.getContentLength()]; ASN1Util.readFully(valBytes, derStream); return new ENUMERATED(valBytes); } catch (InvalidBERException e) { throw new InvalidBERException(e, "ENUMERATED"); } } } // end of Template } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/EXPLICIT.java000066400000000000000000000103231412550063600227330ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; /** * An explicit tag. */ public class EXPLICIT implements ASN1Value { public static final Form FORM = Form.CONSTRUCTED; private ASN1Value content; private Tag tag; /** * Creates an EXPLICIT tag wrapping some other ASN1Value. For example, * for the following ASN.1 snippet: * *

     * MyType [3] EXPLICIT INTEGER
     * 
* * assuming a sample value of 5 for the INTEGER, a MyType could be * created with: * *
     * EXPLICIT myValue = new EXPLICIT(new Tag(3), new INTEGER(5));
     * 
* * @param tag Tag. * @param content Content. */ public EXPLICIT(Tag tag, ASN1Value content) { assert (tag != null && content != null); this.content = content; this.tag = tag; } /** * @return the ASN1Value that is wrapped by this EXPLICIT tag. */ public ASN1Value getContent() { return content; } /** * Returns the Tag of this EXPLICIT tag. */ @Override public Tag getTag() { return tag; } @Override public void encode(OutputStream ostream) throws IOException { encode(tag, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); content.encode(bos); byte[] contentBytes = bos.toByteArray(); ASN1Header head = new ASN1Header(implicitTag, FORM, contentBytes.length); head.encode(ostream); ostream.write(contentBytes); } public static Template getTemplate(Tag tag, ASN1Template content) { return new Template(tag, content); } /** * A template for decoding an object wrapped in an EXPLICIT tag. */ public static class Template implements ASN1Template { private ASN1Template content; private Tag tag; /** * Creates a template for unwrapping an object wrapped in an explicit tag. * For example, to decode: * *
         * MyValue ::= [3] EXPLICIT INTEGER
         * 
* * use: * *
         * EXPLICIT.Template myTemplate = new EXPLICIT.Template(new Tag(3),
         *         new INTEGER.Template());
         * 
* * @param tag The tag value of the EXPLICIT tag. * @param content The template for decoding the object that is wrapped * in the explicit tag. */ public Template(Tag tag, ASN1Template content) { this.content = content; this.tag = tag; } @Override public boolean tagMatch(Tag tag) { return (this.tag.equals(tag)); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(tag, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { try { ASN1Header head = new ASN1Header(istream); head.validate(implicitTag, Form.CONSTRUCTED); ASN1Value val = content.decode(istream); EXPLICIT e = new EXPLICIT(tag, val); // if indefinite content length, consume the end-of-content marker if (head.getContentLength() == -1) { head = new ASN1Header(istream); if (!head.isEOC()) { throw new InvalidBERException("No end-of-contents marker"); } } return e; } catch (InvalidBERException e) { throw new InvalidBERException(e, "EXPLICIT"); } } } // end of Template } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/FieldNotPresentException.java000066400000000000000000000015651412550063600264460ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; /** * An exception thrown when an optional field is not present. */ public class FieldNotPresentException extends java.lang.Exception { private static final long serialVersionUID = 1L; public FieldNotPresentException() { super(); } public FieldNotPresentException(String mesg) { super(mesg); } public FieldNotPresentException(String mesg, Throwable cause) { super(mesg, cause); } public FieldNotPresentException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(mesg, cause, enableSuppression, writableStackTrace); } } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/Form.java000066400000000000000000000013021412550063600224120ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; /** * An enumerated type representing the forms of an ASN.1 value. * The possibilities are PRIMITIVE and CONSTRUCTED. */ public class Form { private String name; private Form() { } private Form(String name) { this.name = name; } public static final Form PRIMITIVE = new Form("PRIMITIVE"); public static final Form CONSTRUCTED = new Form("CONSTRUCTED"); @Override public String toString() { return name; } } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/GeneralizedTime.java000066400000000000000000000030131412550063600245600ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.util.Date; /** * The ASN.1 type GeneralizedTime */ public class GeneralizedTime extends TimeBase { public static final Tag TAG = new Tag(Tag.UNIVERSAL, 24); @Override public Tag getTag() { return TAG; } /** * Creates a GeneralizedTime from a Date. * * @param date Input date. */ public GeneralizedTime(Date date) { super(date); } @Override protected boolean isUTC() { return false; } private static final GeneralizedTime.Template templateInstance = new GeneralizedTime.Template(); public static GeneralizedTime.Template getTemplate() { return templateInstance; } /** * A class for decoding GeneralizedTimes. */ public static class Template extends TimeBase.Template implements ASN1Template { @Override protected Tag getTag() { return TAG; } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override protected boolean isUTC() { return false; } @Override protected TimeBase generateInstance(Date date) { return new GeneralizedTime(date); } } } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/IA5String.java000066400000000000000000000055161412550063600232670ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.CharConversionException; public class IA5String extends CharacterString { public IA5String(char[] chars) throws CharConversionException { super(chars); } public IA5String(String s) throws CharConversionException { super(s); } @Override CharConverter getCharConverter() { return new IA5Converter(); } public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 22); @Override public Tag getTag() { return TAG; } public static Template getTemplate() { return templateInstance; } private static final Template templateInstance = new Template(); // nested class public static class Template extends CharacterString.Template { @Override public Tag getTag() { return IA5String.TAG; } @Override public boolean tagMatch(Tag tag) { return (tag.equals(IA5String.TAG)); } @Override protected CharConverter getCharConverter() { return new IA5Converter(); } @Override protected CharacterString generateInstance(char[] chars) throws CharConversionException { return new IA5String(chars); } @Override protected String typeName() { return "IA5String"; } } // nested class private static class IA5Converter implements CharConverter { @Override public char[] byteToChar(byte[] bytes, int offset, int len) throws CharConversionException { char[] chars = new char[len]; int c; // char index int b; // byte index for (b = offset, c = 0; c < len; b++, c++) { if ((bytes[b] & 0x80) != 0) { throw new CharConversionException("Invalid character: " + bytes[b]); } chars[c] = (char) (bytes[b] & 0x7f); } return chars; } @Override public byte[] charToByte(char[] chars, int offset, int len) throws CharConversionException { byte[] bytes = new byte[len]; int c; // char index int b; // byte index for (c = offset, b = 0; b < len; c++, b++) { if ((chars[c] & 0x7f) != chars[c]) { throw new CharConversionException("Invalid character: " + chars[c]); } bytes[b] = (byte) (chars[c] & 0x7f); } return bytes; } } } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/INTEGER.java000066400000000000000000000146471412550063600226240ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigInteger; import java.util.Random; /** * The ASN.1 type INTEGER. This class extends BigInteger. */ public class INTEGER extends BigInteger implements ASN1Value { private static final long serialVersionUID = 1L; private byte[] encodedContents = null; private byte[] getEncodedContents() { if (encodedContents == null) { encodedContents = toByteArray(); } return encodedContents; } private ASN1Header getHeader(Tag t) { return new ASN1Header(t, FORM, getContentLength()); } public INTEGER(String s) throws NumberFormatException { super(s); } public INTEGER(String s, int r) throws NumberFormatException { super(s, r); } public INTEGER(byte[] bval) throws NumberFormatException { super(bval); } public INTEGER(int sign, byte[] mag) throws NumberFormatException { super(sign, mag); } public INTEGER(int numBits, Random rnd) throws NumberFormatException { super(numBits, rnd); } public INTEGER(int bitLength, int certainty, Random rnd) { super(bitLength, certainty, rnd); } public INTEGER(long val) { super(BigInteger.valueOf(val).toByteArray()); } public INTEGER(BigInteger bi) { super(bi.toByteArray()); } public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 2); @Override public Tag getTag() { return TAG; } public static final Form FORM = Form.PRIMITIVE; @Override public void encode(OutputStream outStream) throws IOException { encode(getTag(), outStream); } @Override public void encode(Tag implicitTag, OutputStream outStream) throws IOException { // write header getHeader(implicitTag).encode(outStream); // write contents outStream.write(getEncodedContents()); } public long getContentLength() { return getEncodedContents().length; } public byte[] encode() throws IOException { ByteArrayOutputStream b = new ByteArrayOutputStream(); encode(b); return b.toByteArray(); } private static final INTEGER.Template templateInstance = new INTEGER.Template(); public static ASN1Template getTemplate() { return templateInstance; } /** * Tests the DER encoding and decoding of the INTEGER class. * * @param args Arguments. */ public static void main(String args[]) { try { int[] Is = new int[11]; int[][] Bs = new int[11][]; int i = 0; Is[i] = 0; Bs[i++] = new int[] { 0x02, 0x01, 0x00 }; Is[i] = 1; Bs[i++] = new int[] { 0x02, 0x01, 0x01 }; Is[i] = -1; Bs[i++] = new int[] { 0x02, 0x01, 0xff }; Is[i] = 127; Bs[i++] = new int[] { 0x02, 0x01, 0x7f }; Is[i] = 128; Bs[i++] = new int[] { 0x02, 0x02, 0x00, 0x80 }; Is[i] = 255; Bs[i++] = new int[] { 0x02, 0x02, 0x00, 0xff }; Is[i] = 256; Bs[i++] = new int[] { 0x02, 0x02, 0x01, 0x00 }; Is[i] = -128; Bs[i++] = new int[] { 0x02, 0x01, 0x80 }; Is[i] = -129; Bs[i++] = new int[] { 0x02, 0x02, 0xff, 0x7f }; Is[i] = 43568; Bs[i++] = new int[] { 0x02, 0x03, 0x00, 0xaa, 0x30 }; Is[i] = -43568; Bs[i++] = new int[] { 0x02, 0x03, 0xff, 0x55, 0xd0 }; for (i = 0; i < Is.length; i++) { INTEGER I = new INTEGER(Is[i]); byte[] compare = I.encode(); if (!arraysEqual(compare, Bs[i])) { System.err.println("Encoding FAILED: " + Is[i]); System.exit(-1); } ByteArrayInputStream bis = new ByteArrayInputStream(compare); Template template = new Template(); INTEGER create = (INTEGER) template.decode(bis); if (create.intValue() != Is[i]) { System.err.println("Decoding FAILED: " + Is[i]); System.exit(-1); } } System.out.println("PASS"); } catch (Exception e) { e.printStackTrace(); } } private static boolean arraysEqual(byte[] bytes, int[] ints) { if (bytes == null || ints == null) { return false; } if (bytes.length != ints.length) { return false; } for (int i = 0; i < bytes.length; i++) { if (bytes[i] != (byte) ints[i]) { return false; } } return true; } /////////////////////////////////////////////////////////////////////// // INTEGER.Template // This is a nested class. // public static class Template implements ASN1Template { Tag getTag() { return INTEGER.TAG; } @Override public boolean tagMatch(Tag tag) { return (tag.equals(INTEGER.TAG)); } @Override public ASN1Value decode(InputStream derStream) throws InvalidBERException, IOException { return decode(getTag(), derStream); } @Override public ASN1Value decode(Tag tag, InputStream derStream) throws InvalidBERException, IOException { try { ASN1Header wrapper = new ASN1Header(derStream); wrapper.validate(tag, FORM); // Is length < 1 ? if (wrapper.getContentLength() < 1) { throw new InvalidBERException("Invalid 0 length for INTEGER"); } byte[] valBytes = new byte[(int) wrapper.getContentLength()]; ASN1Util.readFully(valBytes, derStream); return new INTEGER(valBytes); } catch (InvalidBERException e) { throw new InvalidBERException(e, "INTEGER"); } } } // end of class Template } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/InvalidBERException.java000066400000000000000000000044201412550063600253110ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.util.Vector; /** * An exception thrown when BER decoding fails. */ public class InvalidBERException extends java.lang.Exception { private static final long serialVersionUID = 1L; private InvalidBERException child = null; private Vector mesgList = new Vector<>(); public InvalidBERException(String mesg) { super(mesg); } public void append(String mesg) { mesgList.addElement(mesg); } public InvalidBERException(InvalidBERException e, String mesg) { super(mesg); child = e; } /** * Prints out the exception class and error message, including * all the nested exceptions. */ private void appendMessages(StringBuffer sb) { int numMessages = mesgList.size(); for (int i = numMessages - 1; i >= 0; --i) { sb.append(mesgList.elementAt(i)); sb.append(" >> "); } sb.append(getMessage()); } @Override public String toString() { StringBuffer sb = new StringBuffer(); sb.append(this.getClass().getName()); sb.append(": "); appendMessages(sb); return sb.toString(); } public String toStringNested() { StringBuffer sb = new StringBuffer(); appendMessages(sb); if (child != null) { sb.append(" >> "); sb.append(child.toStringNested()); } return sb.toString(); } public static class EOF extends InvalidBERException { private static final long serialVersionUID = 1L; public EOF() { super("Unexpected end-of-file encountered"); } } public static class InvalidChar extends InvalidBERException { private static final long serialVersionUID = 1L; public InvalidChar(byte b, int offset) { super("Invalid character (" + b + ") encountered at offset " + offset); } public InvalidChar(char c, int offset) { super("Invalid character (" + c + ") encountered at offset" + offset); } } } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/NULL.java000066400000000000000000000043561412550063600222750ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.OutputStream; import java.io.InputStream; import java.io.IOException; public class NULL implements ASN1Value { public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 5); @Override public Tag getTag() { return TAG; } public static final Form FORM = Form.PRIMITIVE; @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { ASN1Header head = new ASN1Header(implicitTag, FORM, 0); head.encode(ostream); } private static final NULL instance = new NULL(); public static NULL getInstance() { return instance; } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } public static class Template implements ASN1Template { public Tag getTag() { return NULL.TAG; } @Override public boolean tagMatch(Tag tag) { return (tag.equals(NULL.TAG)); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(getTag(), istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { try { ASN1Header head = new ASN1Header(istream); head.validate(implicitTag, FORM); if (head.getContentLength() != 0) { throw new InvalidBERException("Invalid length (" + head.getContentLength() + ") for NULL; only 0 is permitted"); } return new NULL(); } catch (InvalidBERException e) { throw new InvalidBERException(e, "NULL"); } } } // end of Template } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/OBJECT_IDENTIFIER.java000066400000000000000000000445231412550063600241730ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.StringTokenizer; import java.util.Vector; public class OBJECT_IDENTIFIER implements ASN1Value { /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Standard object identifiers /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// /** * The OID space for EC */ public static final OBJECT_IDENTIFIER EC_PUBKEY_OID = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 10045, 2, 1 }); /** * The OID space for RSA Data Security, Inc. */ public static final OBJECT_IDENTIFIER RSADSI = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549 }); /** * The OID space for RSA's PKCS (public key cryptography standards). */ public static final OBJECT_IDENTIFIER PKCS = RSADSI.subBranch(1); /** * The OID space for RSA's PKCS #1. */ public static final OBJECT_IDENTIFIER PKCS1 = PKCS.subBranch(1); /** * The OID space for RSA's PKCS #2, which has since been folded into * PKCS #1. */ public static final OBJECT_IDENTIFIER PKCS2 = PKCS.subBranch(2); /** * The OID space for RSA's message digest algorithms. */ public static final OBJECT_IDENTIFIER RSA_DIGEST = RSADSI.subBranch(2); /** * The OID space for RSA's password-based encryption standard. */ public static final OBJECT_IDENTIFIER PKCS5 = PKCS.subBranch(5); /** * The OID space for RSA's Selected Attribute Types standard, PKCS #9. */ public static final OBJECT_IDENTIFIER PKCS9 = PKCS.subBranch(9); /** * The OID space for RSA's personal information exchange syntax standard. */ public static final OBJECT_IDENTIFIER PKCS12 = PKCS.subBranch(12); /** * The OID space for RSA's ciphers. */ public static final OBJECT_IDENTIFIER RSA_CIPHER = RSADSI.subBranch(3); /** * The OID space for FIPS standardized algorithms. */ public static final OBJECT_IDENTIFIER ALGORITHM = new OBJECT_IDENTIFIER(new long[] { 1, 3, 14, 3, 2 }); /** * The OID space for FIPS-180-2 SHA256/SHA384/SHA512 standardized algorithms. */ public static final OBJECT_IDENTIFIER HASH_ALGORITHM = new OBJECT_IDENTIFIER( new long[] { 2, 16, 840, 1, 101, 3, 4, 2 }); /** * The OID space for PKIX. */ public static final OBJECT_IDENTIFIER PKIX = new OBJECT_IDENTIFIER(new long[] { 1, 3, 6, 1, 5, 5, 7 }); public static final OBJECT_IDENTIFIER id_cmc = PKIX.subBranch(7); /** * CMC control attributes */ public static final OBJECT_IDENTIFIER id_cmc_cMCStatusInfo = id_cmc.subBranch(1); public static final OBJECT_IDENTIFIER id_cmc_identification = id_cmc.subBranch(2); public static final OBJECT_IDENTIFIER id_cmc_identityProof = id_cmc.subBranch(3); public static final OBJECT_IDENTIFIER id_cmc_dataReturn = id_cmc.subBranch(4); public static final OBJECT_IDENTIFIER id_cmc_transactionId = id_cmc.subBranch(5); public static final OBJECT_IDENTIFIER id_cmc_senderNonce = id_cmc.subBranch(6); public static final OBJECT_IDENTIFIER id_cmc_recipientNonce = id_cmc.subBranch(7); public static final OBJECT_IDENTIFIER id_cmc_addExtensions = id_cmc.subBranch(8); public static final OBJECT_IDENTIFIER id_cmc_encryptedPOP = id_cmc.subBranch(9); public static final OBJECT_IDENTIFIER id_cmc_decryptedPOP = id_cmc.subBranch(10); public static final OBJECT_IDENTIFIER id_cmc_lraPOPWitness = id_cmc.subBranch(11); public static final OBJECT_IDENTIFIER id_cmc_getCert = id_cmc.subBranch(15); public static final OBJECT_IDENTIFIER id_cmc_getCRL = id_cmc.subBranch(16); public static final OBJECT_IDENTIFIER id_cmc_revokeRequest = id_cmc.subBranch(17); public static final OBJECT_IDENTIFIER id_cmc_regInfo = id_cmc.subBranch(18); public static final OBJECT_IDENTIFIER id_cmc_responseInfo = id_cmc.subBranch(19); public static final OBJECT_IDENTIFIER id_cmc_QueryPending = id_cmc.subBranch(21); public static final OBJECT_IDENTIFIER id_cmc_idPOPLinkRandom = id_cmc.subBranch(22); public static final OBJECT_IDENTIFIER id_cmc_idPOPLinkWitness = id_cmc.subBranch(23); public static final OBJECT_IDENTIFIER id_cmc_idConfirmCertAcceptance = id_cmc.subBranch(24); // rfc 5272 public static final OBJECT_IDENTIFIER id_cmc_statusInfoV2 = id_cmc.subBranch(25); public static final OBJECT_IDENTIFIER id_cmc_trustedAnchors = id_cmc.subBranch(26); public static final OBJECT_IDENTIFIER id_cmc_authData = id_cmc.subBranch(27); public static final OBJECT_IDENTIFIER id_cmc_batchRequests = id_cmc.subBranch(28); public static final OBJECT_IDENTIFIER id_cmc_batchResponses = id_cmc.subBranch(29); public static final OBJECT_IDENTIFIER id_cmc_publishCert = id_cmc.subBranch(30); public static final OBJECT_IDENTIFIER id_cmc_modCertTemplate = id_cmc.subBranch(31); public static final OBJECT_IDENTIFIER id_cmc_controlProcessed = id_cmc.subBranch(32); public static final OBJECT_IDENTIFIER id_cmc_popLinkWitnessV2 = id_cmc.subBranch(33); public static final OBJECT_IDENTIFIER id_cmc_identityProofV2 = id_cmc.subBranch(34); public static final OBJECT_IDENTIFIER id_cct = PKIX.subBranch(12); public static final OBJECT_IDENTIFIER id_cct_PKIData = id_cct.subBranch(2); public static final OBJECT_IDENTIFIER id_cct_PKIResponse = id_cct.subBranch(3); public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 6); @Override public Tag getTag() { return TAG; } public static final Form FORM = Form.PRIMITIVE; private long[] numbers; /** * Creates an OBJECT_IDENTIFIER from an array of longs, which constitute * the numbers that make up the OBJECT IDENTIFIER. * * @param numbers Numbers. */ public OBJECT_IDENTIFIER(long[] numbers) { checkLongArray(numbers); this.numbers = numbers; } /** * Checks the given array of numbers to see if it is a valid OID. * This is not an exhaustive test, it just looks for obvious problems. * It will throw an assertion if a problem is found. With DEBUG turned * off, it just checks for null. */ private static void checkLongArray(long[] numbers) { assert (numbers != null); if (numbers == null) { throw new NullPointerException(); } assert (numbers.length >= 2); assert (numbers[0] == 0 || numbers[0] == 1 || numbers[0] == 2); } /** * Creates an OBJECT_IDENTIFIER from a String version. The proper format * for the OID string is dotted numbers, for example: * "3.2.456.53.23.64". * * Because the toString() method here provides a different format, we also * allow that format, for example: * "{3 2 456 53 23 64}". * * @param dottedOID OID string. * @exception NumberFormatException If the given string cannot be * parsed into an OID. */ public OBJECT_IDENTIFIER(String dottedOID) throws NumberFormatException { if (dottedOID == null || dottedOID.length() == 0) { throw new NumberFormatException("OID string is zero-length"); } if (dottedOID.startsWith("{")) { // input string is of the format provided by OBJECT_IDENTIFIER,toString() // convert this first to dotted OID // remove the leading and trailing brackets dottedOID = dottedOID.substring(1, dottedOID.length() - 1); // convert spaces to dots dottedOID = dottedOID.replaceAll(" ", "."); } StringTokenizer stok = new StringTokenizer(dottedOID, "."); numbers = new long[stok.countTokens()]; int i = 0; while (stok.hasMoreElements()) { numbers[i++] = Long.parseLong(stok.nextToken()); } assert (i == numbers.length); checkLongArray(numbers); } public long[] getNumbers() { return numbers; } @Override public int hashCode() { int code = 1; for (int i = 0; i < numbers.length; i++) { code = (int) (code + numbers[i]) * 10; } return code; } /** * Creates a new OBJECT_IDENTIFIER that is a sub-branch of this one. * For example, if OBJECT_IDENTIFIER oid has the value * { 1 3 5 6 }, * then calling oid.subBranch(4) would return a new * OBJECT_IDENTIFIER with the value { 1 3 5 6 4 }. * * @param num Number. * @return New sub-branch. */ public OBJECT_IDENTIFIER subBranch(long num) { long[] nums = new long[numbers.length + 1]; System.arraycopy(numbers, 0, nums, 0, numbers.length); nums[numbers.length] = num; return new OBJECT_IDENTIFIER(nums); } /** * Creates a new OBJECT_IDENTIFIER that is a sub-branch of this one. * For example, if OBJECT_IDENTIFIER oid has the value * { 1 3 5 6 }, * then calling oid.subBranch(new long[]{ 4, 3}) * would return a new * OBJECT_IDENTIFIER with the value { 1 3 5 6 4 3}. * * @param newNums New numbers. * @return New sub-branch. */ public OBJECT_IDENTIFIER subBranch(long[] newNums) { long[] nums = new long[numbers.length + newNums.length]; System.arraycopy(numbers, 0, nums, 0, numbers.length); System.arraycopy(newNums, 0, nums, numbers.length, newNums.length); return new OBJECT_IDENTIFIER(nums); } @Override public boolean equals(Object obj) { if (obj == null || !(obj instanceof OBJECT_IDENTIFIER)) { return false; } long[] nums = ((OBJECT_IDENTIFIER) obj).numbers; if (nums.length != numbers.length) { return false; } for (int i = 0; i < nums.length; i++) { if (nums[i] != numbers[i]) { return false; } } return true; } @Override public String toString() { String ret = "{" + String.valueOf(numbers[0]); for (int i = 1; i < numbers.length; i++) { ret = ret + " " + numbers[i]; } ret += "}"; return ret; } public String toDottedString() { String ret = String.valueOf(numbers[0]); for (int i = 1; i < numbers.length; i++) { ret = ret + "." + numbers[i]; } return ret; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } private byte[] encodedContents = null; /** * Gets the encoding of the contents, or a cached copy. * Since the content encoding is the same regardless of the Tag, * this only needs to be computed once. */ private byte[] getEncodedContents() { if (encodedContents == null) { encodedContents = computeEncodedContents(); } return encodedContents; } // We cache our encoding for a given tag. 99% of the time, only // one tag will be used for an instance, so we will get a cache hit. // In the remaining 1%, we'll have to recompute the encoding. byte[] cachedEncoding = null; Tag tagForCache = null; /** * Returns the encoding for the given tag. If the encoding for * this tag was previously computed (and no encoding for a different * tag has since been computed), this method returns a cached copy. * Otherwise, the encoding will be recomputed. */ private byte[] getEncoding(Tag tag) { if (!tag.equals(tagForCache)) { // recompute for new tag ByteArrayOutputStream out = new ByteArrayOutputStream(); ASN1Header head = getHeader(tag); try { head.encode(out); } catch (IOException e) { throw new RuntimeException("Unable to encode ASN.1 header: " + e.getMessage(), e); } out.write(getEncodedContents(), 0, getEncodedContents().length); tagForCache = tag; cachedEncoding = out.toByteArray(); } return cachedEncoding; } /** * Compute the ASN1 header for this tag. */ private ASN1Header getHeader(Tag implicitTag) { return new ASN1Header(implicitTag, FORM, getEncodedContents().length); } /** * Actually computes the encoding of this object identifier. */ private byte[] computeEncodedContents() { ByteArrayOutputStream out = new ByteArrayOutputStream(); // handle first number assert (numbers.length >= 2); long n = numbers[0]; assert (n == 0 || n == 1 || n == 2); long outb = (numbers[0] * 40) + numbers[1]; assert (((byte) outb) == outb); out.write((byte) outb); // handle consecutive numbers for (int i = 2; i < numbers.length; i++) { n = numbers[i]; assert (n >= 0); // array of output bytes, in reverse order. 10 bytes, at 7 bits // per byte, is 70 bits, which is more than enough to handle // the maximum value of a long, which takes up 63 bits. byte[] rev = new byte[10]; int idx = 0; // index into reversed bytes // Create reversed byte list do { rev[idx++] = (byte) (n % 128); n = n / 128; } while (n > 0); idx--; // backup to point to last element // now print them in reverse order while (idx > 0) { // all but last byte have MSB==1 out.write(rev[idx--] | 0x80); } assert (idx == 0); // last byte has MSB==0 out.write(rev[0]); } return out.toByteArray(); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { ostream.write(getEncoding(implicitTag)); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /////////////////////////////////////////////////////////////////////// // OBJECT_IDENTIFIER.Template // public static class Template implements ASN1Template { public Tag getTag() { return OBJECT_IDENTIFIER.TAG; } @Override public boolean tagMatch(Tag tag) { return (tag.equals(OBJECT_IDENTIFIER.TAG)); } public Form getForm() { return OBJECT_IDENTIFIER.FORM; } public boolean formMatch(Form form) { return (form == OBJECT_IDENTIFIER.FORM); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(getTag(), istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { try { ASN1Header head = new ASN1Header(istream); long remainingContent = head.getContentLength(); // Check the information gleaned from the header if (!head.getTag().equals(implicitTag)) { throw new InvalidBERException("Incorrect tag for " + "OBJECT IDENTIFIER: " + head.getTag()); } if (head.getForm() != getForm()) { throw new InvalidBERException("Incorrect form for OBJECT " + "IDENTIFIER"); } if (remainingContent < 1) { throw new InvalidBERException("Invalid 0 length for OBJECT" + " IDENTIFIER"); } Vector numberV = new Vector<>(); // handle first byte, which contains first two numbers byte b = readByte(istream); remainingContent--; long num = b % 40; numberV.addElement(Long.valueOf(b % 40)); // second number numberV.insertElementAt(Long.valueOf(b / 40), 0); // first number // handle the rest of the numbers while (remainingContent > 0) { num = 0; // keep reading until MSB == 0 int bitcount = 0; do { if ((bitcount += 7) > 63) { // we're about to overflow our long throw new InvalidBERException("OBJECT IDENTIFIER " + "element too long; max is 63 bits"); } b = readByte(istream); remainingContent--; num <<= 7; num |= (b & 0x7f); } while ((b & 0x80) != 0); numberV.addElement(Long.valueOf(num)); } // convert Vector to array long numbers[] = new long[numberV.size()]; for (int i = 0; i < numbers.length; i++) { numbers[i] = numberV.elementAt(i).longValue(); } // create OBJECT_IDENTIFIER from array return new OBJECT_IDENTIFIER(numbers); } catch (InvalidBERException e) { throw new InvalidBERException(e, "OBJECT IDENTIFIER"); } } /** * Reads in a byte from the stream, throws an InvalidBERException * if EOF is reached. */ private static byte readByte(InputStream istream) throws InvalidBERException, IOException { int n = istream.read(); if (n == -1) { throw new InvalidBERException("End-of-file reached while " + "decoding OBJECT IDENTIFIER"); } assert ((n & 0xff) == n); return (byte) n; } } // end of OBJECT_IDENTIFIER.Template } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/OCTET_STRING.java000066400000000000000000000066501412550063600234660ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class OCTET_STRING implements ASN1Value { public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 4); @Override public Tag getTag() { return TAG; } public static final Form FORM = Form.PRIMITIVE; byte[] data; public OCTET_STRING(byte[] data) { this.data = data; } public byte[] toByteArray() { return data; } @Override public void encode(OutputStream ostream) throws IOException { // use getTag() so we can be subclassed encode(getTag(), ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { ASN1Header head = new ASN1Header(implicitTag, FORM, data.length); head.encode(ostream); ostream.write(data); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } public static class Template implements ASN1Template { public Tag getTag() { return TAG; } @Override public boolean tagMatch(Tag tag) { return (TAG.equals(tag)); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(getTag(), istream); } // this can be overridden by subclasses protected ASN1Value generateInstance(byte[] bytes) { return new OCTET_STRING(bytes); } // this can be overridden by subclasses protected String getName() { return "OCTET_STRING"; } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { try { ASN1Header head = new ASN1Header(istream); head.validate(implicitTag); byte[] data; if (head.getContentLength() == -1) { // indefinite length encoding ASN1Header ahead; ByteArrayOutputStream bos = new ByteArrayOutputStream(); do { ahead = ASN1Header.lookAhead(istream); if (!ahead.isEOC()) { OCTET_STRING.Template ot = new OCTET_STRING.Template(); OCTET_STRING os = (OCTET_STRING) ot.decode(istream); bos.write(os.toByteArray()); } } while (!ahead.isEOC()); // consume EOC ahead = new ASN1Header(istream); data = bos.toByteArray(); } else { data = new byte[(int) head.getContentLength()]; ASN1Util.readFully(data, istream); } return generateInstance(data); } catch (InvalidBERException e) { throw new InvalidBERException(e, getName()); } } } // end of Template } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/PrintableString.java000066400000000000000000000101011412550063600246130ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.CharConversionException; public class PrintableString extends CharacterString { public PrintableString(char[] chars) throws CharConversionException { super(chars); } public PrintableString(String s) throws CharConversionException { super(s); } @Override CharConverter getCharConverter() { return new PrintableConverter(); } public static final Tag TAG = new Tag(Tag.UNIVERSAL, 19); public static final Form FORM = Form.PRIMITIVE; @Override public Tag getTag() { return TAG; } /** * Returns a singleton instance of the decoding template for this class. * * @return The template. */ public static Template getTemplate() { return templateInstance; } private static final Template templateInstance = new Template(); // nested class public static class Template extends CharacterString.Template { @Override protected Tag getTag() { return TAG; } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override protected CharConverter getCharConverter() { return new PrintableConverter(); } @Override protected CharacterString generateInstance(char[] chars) throws CharConversionException { return new PrintableString(chars); } @Override protected String typeName() { return "PrintableString"; } } private static class PrintableConverter implements CharConverter { private static boolean[] isPrintable = new boolean[128]; static { char b; for (b = 'A'; b <= 'Z'; b++) { isPrintable[b] = true; } for (b = 'a'; b <= 'z'; b++) { isPrintable[b] = true; } for (b = '0'; b <= '9'; b++) { isPrintable[b] = true; } isPrintable[' '] = true; isPrintable['\''] = true; isPrintable['('] = true; isPrintable[')'] = true; isPrintable['+'] = true; isPrintable[','] = true; isPrintable['-'] = true; isPrintable['.'] = true; isPrintable['/'] = true; isPrintable[':'] = true; isPrintable['='] = true; isPrintable['?'] = true; } @Override public char[] byteToChar(byte[] bytes, int offset, int len) throws CharConversionException { char[] chars = new char[len]; int c; // char index int b; // byte index for (c = 0, b = offset; c < len; b++, c++) { if ((bytes[b] & 0x80) != 0 || !isPrintable[bytes[b]]) { /* fix for bug 359010 - don't throw, just skip * throw new CharConversionException(bytes[b]+ " is not "+ * "a valid character for a PrintableString"); */ } else { chars[c] = (char) bytes[b]; } } return chars; } @Override public byte[] charToByte(char[] chars, int offset, int len) throws CharConversionException { byte[] bytes = new byte[len]; int c; // char index int b; // byte index for (c = 0, b = 0; b < len; b++, c++) { if ((chars[c] & 0xff80) != 0 || !isPrintable[chars[c]]) { throw new CharConversionException(chars[c] + " is not " + "a valid character for a PrintableString"); } bytes[b] = (byte) (chars[c] & 0x7f); } return bytes; } } // end of char converter } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/SEQUENCE.java000066400000000000000000000723431412550063600227340ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Vector; /** * An ASN.1 SEQUENCE. This class is an ordered collection of ASN.1 values. * It has an interface similar to a Java Vector. * Null entries may be added; they will be skipped when encoded. */ public class SEQUENCE extends SET { public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 16); @Override public Tag getTag() { return TAG; } public static Template getTemplate() { return new Template(); } /** * Writes the DER encoding to the given output stream, * using the given implicit tag. */ @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { BERencode(implicitTag, ostream); } // SET.Element and SEQUENCE.Element are identical types. We could // have just reused SET.Element, but that would have been a bit // confusing for users. private static class Element extends SET.Element { public Element(ASN1Value val) { super(val); } public Element(Tag implicitTag, ASN1Value val) { super(implicitTag, val); } } /** * A class for constructing a SEQUENCE from its BER encoding. * It is an ordered collection of sub-templates. Each sub-template can be * marked optional, or a default value can be given. */ public static class Template implements ASN1Template { private Vector elements = new Vector<>(); private void addElement(Element el) { elements.addElement(el); } private void insertElementAt(Element e, int index) { elements.insertElementAt(e, index); } /** * Adds a sub-template to the end of this SEQUENCE template. For example, * if the ASN.1 included: * *
         * MySequence ::= SEQUENCE {
         *      item        SubType,
         *      ... }
         * 
* * the "item" element would be added to the MySequence template with: * *
         * mySequence.addElement(new SubType.Template());
         * 
* * @param t Sub-template. */ public void addElement(ASN1Template t) { addElement(new Element(null, t, false)); } /** * Inserts the template at the given index. * * @param t Sub-template. * @param index Index. */ public void insertElementAt(ASN1Template t, int index) { insertElementAt(new Element(null, t, false), index); } /** * Adds a sub-template to the end of this SEQUENCE template, with the * given implicit tag. For example, if the ASN.1 were: * *
         * MySequence ::= SEQUENCE {
         *      item        [0] IMPLICIT  SubType,
         *      ... }
         * 
* * the "item" element would be added to the MySequence template with: * *
         * mySequence.addElement(new Tag(0), new SubType.Template());
         * 
* * @param implicitTag Implicit tag. * @param t Sub-template. */ public void addElement(Tag implicitTag, ASN1Template t) { addElement(new Element(implicitTag, t, false)); } /** * Inserts the template with the given implicit tag at the given index. * * @param implicit Implicit tag. * @param t Sub-Template. * @param index Index. */ public void insertElementAt(Tag implicit, ASN1Template t, int index) { insertElementAt(new Element(implicit, t, false), index); } /** * Adds an optional sub-template. For example, if the ASN.1 were: * *
         * MySequence ::= SEQUENCE {
         *      item        SubType OPTIONAL,
         *      ... }
         * 
* * the "item" element would be added to the MySequence template with: * *
         * mySequence.addOptionalElement(new SubType.Template());
         * 
* * @param t Optional sub-template. */ public void addOptionalElement(ASN1Template t) { addElement(new Element(null, t, true)); } /** * Inserts the optional template at the given index. * * @param t Optional sub-template. * @param index Index. */ public void insertOptionalElementAt(ASN1Template t, int index) { insertElementAt(new Element(null, t, true), index); } /** * Adds an optional sub-template with an implicit tag. For example, * if the ASN.1 were: * *
         * MySequence ::= SEQUENCE {
         *      item        [0] IMPLICIT SubType OPTIONAL,
         *      ... }
         * 
* * the "item" element would be added to the MySequence template with: * *
         * mySequence.addOptionalElement(new SubType.Template());
         * 
* * @param implicitTag Implicit tag. * @param t Optional sub-template. */ public void addOptionalElement(Tag implicitTag, ASN1Template t) { addElement(new Element(implicitTag, t, true)); } /** * Inserts the optional template with the given default * value at the given index. * * @param implicit Implicit tag. * @param t Optional sub-template. * @param index Index. */ public void insertOptionalElementAt(Tag implicit, ASN1Template t, int index) { insertElementAt(new Element(implicit, t, true), index); } /** * Adds a sub-template with a default value. For example, * if the ASN.1 were: * *
         * MySequence ::= SEQUENCE {
         *      version     INTEGER DEFAULT 1,
         *      ... }
         * 
* * the "item" element would be added to the MySequence template with: * *
         * mySequence.addElement(new INTEGER.Template(), new INTEGER(1));
         * 
* * @param t Sub-template. * @param def The default value for this field, which will be used if * no value is supplied by the encoded structure. It must be of * the same type as what the template would produce. */ public void addElement(ASN1Template t, ASN1Value def) { addElement(new Element(null, t, def)); } /** * Inserts the template with the given default * value at the given index. * * @param t Sub-template. * @param def Default value. * @param index Index. */ public void insertElementAt(ASN1Template t, ASN1Value def, int index) { insertElementAt(new Element(null, t, def), index); } /** * Adds a sub-template with a default value and an implicit tag. * For example, if the ASN.1 were: * *
         * MySequence ::= SEQUENCE {
         *      version     [0] IMPLICIT INTEGER DEFAULT 1,
         *      ... }
         * 
* * the "item" element would be added to the MySequence template with: * *
         * mySequence.addElement(new Tag(0), new INTEGER.Template(),
         *         new INTEGER(1));
         * 
* * @param implicitTag Implicit tag. * @param t Sub-template. * @param def The default value for this field, which will be used if * no value is supplied by the encoded structure. It must be of * the same type as what the template would produce. */ public void addElement(Tag implicitTag, ASN1Template t, ASN1Value def) { addElement(new Element(implicitTag, t, def)); } /** * Inserts the template with the given implicit tag and given default * value at the given index. * * @param implicit Implicit tag. * @param t Sub-template. * @param def Default value. * @param index Index. */ public void insertElementAt(Tag implicit, ASN1Template t, ASN1Value def, int index) { insertElementAt(new Element(implicit, t, def), index); } /** * Returns the implicit tag of the item stored at the given index. * May be NULL if no implicit tag was specified. * * @param index Index. * @return Tag. */ public Tag implicitTagAt(int index) { return elements.elementAt(index).getImplicitTag(); } /** * Returns the sub-template stored at the given index. * * @param index Index. * @return Sub-template. */ public ASN1Template templateAt(int index) { return elements.elementAt(index).getTemplate(); } /** * Returns whether the sub-template at the given index is optional. * * @param index Index. * @return True if the sub-template is optional. */ public boolean isOptionalAt(int index) { return elements.elementAt(index).isOptional(); } /** * Returns the default value for the sub-template at the given index. * May return NULL if no default value was specified. * * @param index Index. * @return Default value. */ public ASN1Value defaultAt(int index) { return elements.elementAt(index).getDefault(); } /** * @return The number of elements in this SEQUENCE template. */ public int size() { return elements.size(); } /** * Removes all sub-templates from this SEQUENCE template. */ public void removeAllElements() { elements.removeAllElements(); } /** * Removes the sub-template at the given index. * * @param index Index. */ public void removeElementAt(int index) { elements.removeElementAt(index); } Tag getTag() { return SEQUENCE.TAG; } @Override public boolean tagMatch(Tag tag) { return (tag.equals(SEQUENCE.TAG)); } /** * Decodes a SEQUENCE from its BER encoding. * * @param istream Input stream. */ @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(getTag(), istream); } /** * Decodes a SEQUENCE from its BER encoding, where the SEQUENCE itself has * an implicit tag. * * @param tag Tag. * @param istream Input stream. */ @Override public ASN1Value decode(Tag tag, InputStream istream) throws IOException, InvalidBERException { int index = 0; try { ASN1Header header = new ASN1Header(istream); header.validate(tag, Form.CONSTRUCTED); // will be -1 for indefinite encoding long remainingContent = header.getContentLength(); boolean repeatableElement = false; SEQUENCE seq = new SEQUENCE(); ASN1Header lookAhead = null; // go through the whole template for (index = 0; index < size(); index++) { // find out about the next item if (remainingContent == 0) { lookAhead = null; } else { // remainingContent > 0 or remainingContent == -1, which means // indefinite encoding. lookAhead = ASN1Header.lookAhead(istream); } // skip over items that don't match. Hopefully they are // optional or have a default. Otherwise, it's an error. Element e = elements.elementAt(index); if ((lookAhead == null) || lookAhead.isEOC() || !e.tagMatch(lookAhead.getTag())) { if (e.isRepeatable()) { repeatableElement = true; } else if (e.isOptional()) { // put an empty entry into the SEQUENCE SEQUENCE.Element se = new SEQUENCE.Element(null, null); seq.addElement(null); } else if (e.getDefault() != null) { // use the default seq.addElement(e.getDefault()); } else { String tagDesc; if (lookAhead == null) { tagDesc = "(null)"; } else { tagDesc = lookAhead.getTag().toString(); } throw new InvalidBERException("Missing item #" + index + ": found " + tagDesc); } continue; } // Decode this element ASN1Template t = e.getTemplate(); ASN1Value val; try (CountingStream countstream = new CountingStream(istream)) { if (e.getImplicitTag() == null) { val = t.decode(countstream); } else { val = t.decode(e.getImplicitTag(), countstream); } // Decrement remaining count long len = countstream.getNumRead(); if (remainingContent != -1) { if (remainingContent < len) { // this item went past the end of the SEQUENCE throw new InvalidBERException("Item went " + (len - remainingContent) + " bytes past the end of" + " the SEQUENCE"); } remainingContent -= len; } } // Store this element in the SEQUENCE if (e.producesOutput()) { if (e.getImplicitTag() == null) { // no implicit tag seq.addElement(val); } else { // there is an implicit tag seq.addElement(e.getImplicitTag(), val); } } // If this element is repeatable, don't go on to the next element if (e.isRepeatable()) { repeatableElement = true; index--; } } if (remainingContent > 0) { throw new InvalidBERException("SEQUENCE is " + remainingContent + " bytes longer than expected"); } assert (remainingContent == 0 || remainingContent == -1); // If this was indefinite-length encoding, consume the end-of-contents if (remainingContent == -1) { lookAhead = new ASN1Header(istream); if (!lookAhead.isEOC()) { throw new InvalidBERException("No end-of-contents marker"); } } // Make sure we stayed in sync if (!repeatableElement) { assert (index == seq.size()); } return seq; } catch (InvalidBERException e) { e.append("SEQUENCE(item #" + index + ")"); throw e; } } /** * An element of a SEQUENCE template. For each sub-template, contains the * template, its optionality, its implicit tag, and its default value. */ static class Element { /** * Creates a new element, which may or may not be optional. * * @param implicitTag Implicit tag. * @param type Type. * @param optional Optional. */ public Element(Tag implicitTag, ASN1Template type, boolean optional) { this(implicitTag, type, optional, true); } /** * Creates a new element, which may or may not be optional. * * @param implicitTag Implicit tag. * @param type Type. * @param optional Optional. * @param doesProduceOutput True if produces output. */ public Element(Tag implicitTag, ASN1Template type, boolean optional, boolean doesProduceOutput) { this.type = type; defaultVal = null; this.optional = optional; this.implicitTag = implicitTag; this.doesProduceOutput = doesProduceOutput; } /** * Creates a new element with a default value. * * @param implicitTag Implicit tag. * @param type Type. * @param defaultVal Default value. */ public Element(Tag implicitTag, ASN1Template type, ASN1Value defaultVal) { this.type = type; this.defaultVal = defaultVal; optional = false; this.implicitTag = implicitTag; } private boolean doesProduceOutput = true; boolean producesOutput() { return doesProduceOutput; } // repeatability is provided to allow for SEQUENCE OF SIZE // constructs. It is package private. private boolean repeatable; void makeRepeatable() { repeatable = true; } boolean isRepeatable() { return repeatable; } private boolean optional; public boolean isOptional() { return optional; } private Tag implicitTag = null; public Tag getImplicitTag() { return implicitTag; } public boolean tagMatch(Tag tag) { if (implicitTag != null) { return (implicitTag.equals(tag)); } else { return type.tagMatch(tag); } } private ASN1Template type; public ASN1Template getTemplate() { return type; } private ASN1Value defaultVal = null; public ASN1Value getDefault() { return defaultVal; } } } // End of SEQUENCE.Template /** * A Template for decoding SEQUENCE OF values. The main difference between * a SEQUENCE.Template and a SEQUENCE.OF_Template is that a regular template * specifies the exact ordering, number, and type of elements of the sequence, * while * an OF_Template has an indefinite number of elements, all the same type. * For example, given: * *
     * MyType ::= SEQUENCE OF Extension
     * 
* * a MyType could be decoded with: * *
     *  SEQUENCE.OF_Template myTypeTemplate = new SEQUENCE.OF_Template( new
     *      Extension.Template) );
     *  SEQUENCE seq = (SEQUENCE) myTypeTemplate.decode(someInputStream);
     * 
* * The number of Extensions actually decoded could be found * with seq.size(). */ public static class OF_Template implements ASN1Template { private OF_Template() { } Template template; // a normal SEQUENCE template public OF_Template(ASN1Template type) { template = new Template(); Template.Element el = new Template.Element(null, type, true); //optional el.makeRepeatable(); template.addElement(el); } public static OF_Template makeOutputlessOFTemplate(ASN1Template type) { OF_Template t = new OF_Template(); t.template = new Template(); Template.Element el = new Template.Element(null, type, true, false); el.makeRepeatable(); t.template.addElement(el); return t; } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } /** * Decodes a SEQUENCE OF from an input stream. */ @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return template.decode(istream); } /** * Decodes a SEQUENCE OF with an implicit tag from an input stream. */ @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { return template.decode(implicitTag, istream); } } public static void main(String args[]) { try { if (args.length > 0) { // input Template type = new Template(); type.addOptionalElement(new Tag(15), new INTEGER.Template()); type.addElement(new Tag(16), new INTEGER.Template(), new INTEGER(42)); type.addElement(new INTEGER.Template()); type.addElement(new BOOLEAN.Template()); type.addElement(new INTEGER.Template()); type.addOptionalElement(new Tag(12), new INTEGER.Template()); type.addElement(new BOOLEAN.Template()); type.addElement(new Tag(13), new INTEGER.Template(), new INTEGER(53)); type.addElement(new INTEGER.Template()); type.addElement(new INTEGER.Template()); type.addOptionalElement(new Tag(14), new INTEGER.Template()); type.addElement(new OBJECT_IDENTIFIER.Template()); type.addElement(new NULL.Template()); type.addElement(new EXPLICIT.Template( new Tag(27), new INTEGER.Template())); type.addElement(new ENUMERATED.Template()); type.addElement(new OCTET_STRING.Template()); type.addElement(new IA5String.Template()); CHOICE.Template choice = new CHOICE.Template(); choice.addElement(new Tag(23), new INTEGER.Template()); choice.addElement(new BOOLEAN.Template()); type.addElement(choice); type.addElement(new BIT_STRING.Template()); type.addElement(new ANY.Template()); type.addElement(new PrintableString.Template()); type.addElement(new OF_Template(new INTEGER.Template())); type.addElement(new OF_Template(new INTEGER.Template())); byte[] stuff; try (FileInputStream fin = new FileInputStream(args[0])) { System.out.println("Available: " + fin.available()); stuff = new byte[fin.available()]; ASN1Util.readFully(stuff, fin); } SEQUENCE s = null; for (int i = 0; i < 1; i++) { s = (SEQUENCE) type.decode(new ByteArrayInputStream(stuff)); } for (int i = 0; i < s.size(); i++) { ASN1Value v = s.elementAt(i); if (v instanceof ENUMERATED) { ENUMERATED en = (ENUMERATED) v; System.out.println("ENUMERATED: " + en); } else if (v instanceof INTEGER) { INTEGER in = (INTEGER) v; System.out.println("INTEGER: " + in); } else if (v instanceof BOOLEAN) { BOOLEAN bo = (BOOLEAN) v; System.out.println("BOOLEAN: " + bo); } else if (v instanceof OBJECT_IDENTIFIER) { OBJECT_IDENTIFIER oid = (OBJECT_IDENTIFIER) v; System.out.println("OID: " + oid); } else if (v instanceof NULL) { NULL n = (NULL) v; System.out.println("NULL"); } else if (v instanceof EXPLICIT) { EXPLICIT ex = (EXPLICIT) v; INTEGER in = (INTEGER) ex.getContent(); System.out.println("EXPLICIT [" + ex.getTag() + "]: " + "INTEGER: " + in); } else if (v instanceof OCTET_STRING) { OCTET_STRING os = (OCTET_STRING) v; byte[] bytes = os.toByteArray(); System.out.print("OCTET_STRING: "); for (int j = 0; j < bytes.length; j++) { System.out.print(bytes[j] + " "); } System.out.println(""); } else if (v instanceof CharacterString) { CharacterString cs = (CharacterString) v; System.out.println("String: " + cs); } else if (v instanceof BIT_STRING) { BIT_STRING bs = (BIT_STRING) v; System.out.print("BIT_STRING: padCount=" + bs.getPadCount() + " : "); byte[] bits = bs.getBits(); for (int j = 0; j < bits.length; j++) { System.out.print(bits[j] + " "); } System.out.println(""); } else if (v instanceof ANY) { ANY any = (ANY) v; Tag tag = any.getTag(); System.out.println("Got ANY, tag is " + tag); ByteArrayInputStream bos = new ByteArrayInputStream(any.getEncoded()); INTEGER in = (INTEGER) new INTEGER.Template().decode(bos); System.out.println(" INTEGER: " + in); } else if (v instanceof SEQUENCE) { SEQUENCE seq = (SEQUENCE) v; System.out.println("SEQUENCE: "); for (int j = 0; j < seq.size(); j++) { INTEGER in = (INTEGER) seq.elementAt(j); System.out.println(" INTEGER: " + in); } } else { System.out.println("Unknown value"); } } } else { // output SEQUENCE seq = new SEQUENCE(); seq.addElement(new INTEGER(5)); seq.addElement(new BOOLEAN(true)); seq.addElement(new INTEGER(-322)); seq.addElement(new BOOLEAN(false)); seq.addElement(new INTEGER(0)); seq.addElement(new INTEGER("2934293834242")); seq.addElement(new OBJECT_IDENTIFIER( new long[] { 1, 2, 127, 563, 1231982 })); seq.addElement(new NULL()); seq.addElement(new EXPLICIT(new Tag(27), new INTEGER(39))); seq.addElement(new ENUMERATED(983)); seq.addElement(new OCTET_STRING(new byte[] { (byte) 0x0, (byte) 0xff, (byte) 0xcc })); seq.addElement(new IA5String("foobar")); seq.addElement(new Tag(23), new INTEGER(234)); //seq.addElement( new BOOLEAN(false) ); byte[] bits = new byte[] { (byte) 0x80, (byte) 0xff, (byte) 0x0f }; seq.addElement(new BIT_STRING(bits, 3)); seq.addElement(new INTEGER(82734)); seq.addElement(new PrintableString("I'm printable??")); SEQUENCE nested = new SEQUENCE(); nested.addElement(new INTEGER(5)); nested.addElement(new INTEGER(6)); seq.addElement(nested); nested = new SEQUENCE(); seq.addElement(nested); seq.encode(System.out); System.out.flush(); } } catch (Exception e) { e.printStackTrace(); } } } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/SET.java000066400000000000000000000762501412550063600221600ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.BufferedInputStream; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Vector; /** * An ASN.1 SET, which is an unordered collection of ASN.1 values. * It has an interface like a Java Vector, but the ordering is arbitrary. * Null entries may be added; they will be skipped when encoding. */ public class SET implements ASN1Value { public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 17); @Override public Tag getTag() { return TAG; } protected static final Form FORM = Form.CONSTRUCTED; // The elements of the set protected Vector elements = new Vector<>(); private void addElement(Element e) { elements.addElement(e); } private void insertElementAt(Element e, int index) { elements.insertElementAt(e, index); } /** * Adds an element to this SET. * * @param v Element. */ public void addElement(ASN1Value v) { addElement(new Element(v)); } /** * Adds an element to this SET with the given implicit tag. For example, * if the ASN.1 were: * *
     *  MyType ::= SET {
     *      item        [0] IMPLICIT INTEGER,
     *      ... }
     * 
* * then the "item" element could be added (with a sample value of 45) * to the SET with: * *
     * myTypeInstance.addElement(new Tag(0), new INTEGER(45));
     * 
* * @param implicitTag Implicit tag. * @param v Element. */ public void addElement(Tag implicitTag, ASN1Value v) { addElement(new Element(implicitTag, v)); } /** * Inserts an element at the given index. * * @param v Element. * @param index Index. */ public void insertElementAt(ASN1Value v, int index) { insertElementAt(new Element(v), index); } /** * Inserts an element with the given implicit tag at the given index. * * @param implicitTag Implicit tag. * @param v Element. * @param index Index. */ public void insertElementAt(Tag implicitTag, ASN1Value v, int index) { insertElementAt(new Element(implicitTag, v), index); } /** * Returns the element at the given index in the SET. * * @param index Index. * @return Element. */ public ASN1Value elementAt(int index) { return elements.elementAt(index).getValue(); } /** * Returns the tag of the element at the given index. If the element * has an implicit tag, that is returned. Otherwise, the tag of the * underlying type is returned. * * @param index Index. * @return Tag. */ public Tag tagAt(int index) { Tag implicit = elements.elementAt(index).getImplicitTag(); if (implicit != null) { return implicit; } else { return elementAt(index).getTag(); } } /** * Returns the element with the given Tag, or null if no element exists * with the given tag. * * @param tag Tag. * @return Element. */ public ASN1Value elementWithTag(Tag tag) { // hmmm...linear search for now, should use hashtable later int size = elements.size(); for (int i = 0; i < size; i++) { Element e = elements.elementAt(i); if (e.getTag().equals(tag)) { return e.getValue(); } } return null; } /** * @return The number of elements in this SET. */ public int size() { return elements.size(); } /** * Removes all elements from this SET. */ public void removeAllElements() { elements.removeAllElements(); } /** * Removes the element from the specified index. * * @param index Index. */ public void removeElementAt(int index) { elements.removeElementAt(index); } /** * Writes the DER encoding to the given output stream. * * @param ostream Output stream. */ @Override public void encode(OutputStream ostream) throws IOException { encode(getTag(), ostream); } /** * Writes the DER encoding to the given output stream, * using the given implicit tag. To satisfy DER encoding rules, * the elements will be re-ordered either by tag or lexicographically. * * @param implicitTag Implicit tag. * @param ostream Output stream. */ @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { // what ordering method? boolean lexOrdering; if (elements.size() < 2) { // doesn't matter, only one element lexOrdering = true; } else if (tagAt(0).equals(tagAt(1))) { // tags are the same, lexicographic ordering lexOrdering = true; } else { // tags are different, order by tag lexOrdering = false; } // compute and order contents int numElements = elements.size(); int totalBytes = 0; Vector encodings = new Vector<>(numElements); Vector tags = new Vector<>(numElements); int i; for (i = 0; i < numElements; i++) { // if an entry is null, just skip it if (elementAt(i) != null) { byte[] enc = ASN1Util.encode(tagAt(i), elementAt(i)); totalBytes += enc.length; if (lexOrdering) { insertInOrder(encodings, enc); } else { insertInOrder(encodings, enc, tags, (int) tagAt(i).getNum()); } } } // write header ASN1Header header = new ASN1Header(implicitTag, FORM, totalBytes); header.encode(ostream); // write contents in order for (i = 0; i < numElements; i++) { ostream.write(encodings.elementAt(i)); } } /** * Encodes this SET without re-ordering it. This may violate * DER, but it is within BER. * * @param implicitTag Implicit tag. * @param ostream Output stream. * @throws IOException If an error occurred. */ public void BERencode(Tag implicitTag, OutputStream ostream) throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); // compute contents int size = elements.size(); for (int i = 0; i < size; i++) { ASN1Value el = elementAt(i); if (el != null) { el.encode(tagAt(i), bos); } } byte[] bytes = bos.toByteArray(); // write header ASN1Header header = new ASN1Header(implicitTag, FORM, bytes.length); header.encode(ostream); // write contents ostream.write(bytes); } // performs ascending lexicographic ordering // linear search, but number of items is usually going to be small. private static void insertInOrder(Vector encs, byte[] enc) { int size = encs.size(); // find the lowest item that we are less than or equal to int i; for (i = 0; i < size; i++) { if (compare(enc, encs.elementAt(i)) < 1) { break; } } // insert ourself before this item encs.insertElementAt(enc, i); } // performs ascending ordering by tag // linear search, but number of items is usually going to be small. private static void insertInOrder(Vector encs, byte[] enc, Vector tags, int tag) { int size = encs.size(); // find the lowest item that we are less than or equal to int i; for (i = 0; i < size; i++) { if (tag <= tags.elementAt(i).intValue()) { break; } } // insert ourself before this item encs.insertElementAt(enc, i); tags.insertElementAt(Integer.valueOf(i), i); } // compares two byte arrays // returns 1 if left > right, -1 if left < right, 0 if left == right private static int compare(byte[] left, byte[] right) { int min = (left.length < right.length) ? left.length : right.length; for (int i = 0; i < min; i++) { if ((left[i] & 0xff) < (right[i] & 0xff)) { return -1; } else if ((left[i] & 0xff) > (right[i] & 0xff)) { return 1; } } // equal up to the minimal endpoint if (left.length > min) { assert (right.length == min); return 1; } if (right.length > min) { assert (left.length == min); return -1; } return 0; } /** * An element of a SET */ static class Element { /** * Makes a new SET element from the given value. */ public Element(ASN1Value val) { this.val = val; } /** * Makes a new SET element from the given value with the given * implicit tag. */ public Element(Tag implicitTag, ASN1Value val) { this.val = val; this.implicitTag = implicitTag; } private ASN1Value val; /** * Returns the value of this SET element. */ public ASN1Value getValue() { return val; } /** * Returns the tag that actually shows up in the encoding. * If there is an implicit tag, it will be used. Otherwise, * it will be the base tag for the value. */ public Tag getTag() { if (implicitTag != null) { return implicitTag; } else { return val.getTag(); } } private Tag implicitTag = null; /** * Returns the implicit tag for this value, if there is one. * If not, returns null. */ public Tag getImplicitTag() { return implicitTag; } } /** * SET.Template * This class is used for decoding DER-encoded SETs. */ public static class Template implements ASN1Template { private Vector elements = new Vector<>(); private void addElement(Element e) { elements.addElement(e); } private void insertElementAt(Element e, int index) { elements.insertElementAt(e, index); } /** * Adds a sub-template to the end of this SET template. For example, * if the ASN.1 included: * *
         * MySet ::= SET {
         *      item        SubType,
         *      ... }
         * 
* * the "item" element would be added to the MySet template with: * *
         * mySet.addElement(new SubType.Template());
         * 
* * @param t Sub-template. */ public void addElement(ASN1Template t) { addElement(new Element(TAG, t, false)); } /** * Inserts the template at the given index. * * @param t Sub-template. * @param index Index. */ public void insertElementAt(ASN1Template t, int index) { insertElementAt(new Element(TAG, t, false), index); } /** * Adds a sub-template with the given implicit tag to the end of this * SET template. For example, if the ASN.1 included: * *
         * MySet ::= SET {
         *      item        [0] IMPLICIT SubType,
         *      ... }
         * 
* * the "item" element would be added to the MySet template with: * *
         * mySet.addElement(new Tag(0), new SubType.Template());
         * 
* * @param implicit Implicit tag. * @param t Sub-template. */ public void addElement(Tag implicit, ASN1Template t) { addElement(new Element(implicit, t, false)); } /** * Inserts the template with the given implicit tag at the given index. * * @param implicit Implicit tag. * @param t Sub-template. * @param index Index. */ public void insertElementAt(Tag implicit, ASN1Template t, int index) { insertElementAt(new Element(implicit, t, false), index); } /** * Adds an optional sub-template to the end * of this SET template. For example, if the ASN.1 included: * *
         * MySet ::= SET {
         *      item        SubType OPTIONAL,
         *      ... }
         * 
* * the "item" element would be added to the MySet template with: * *
         * mySet.addOptionalElement(new SubType.Template());
         * 
* * @param t Optional sub-template. */ public void addOptionalElement(ASN1Template t) { addElement(new Element(TAG, t, true)); } /** * Inserts the optional template at the given index. * * @param t Optional sub-template. * @param index Index. */ public void insertOptionalElementAt(ASN1Template t, int index) { insertElementAt(new Element(null, t, true), index); } /** * Adds an optional sub-template with the given implicit tag to the end * of this SET template. For example, if the ASN.1 included: * *
         * MySet ::= SET {
         *      item        [0] IMPLICIT SubType OPTIONAL,
         *      ... }
         * 
* * the "item" element would be added to the MySet template with: * *
         * mySet.addOptionalElement(new Tag(0), new SubType.Template());
         * 
* * @param implicit Implicit tag. * @param t Optional sub-template. */ public void addOptionalElement(Tag implicit, ASN1Template t) { addElement(new Element(implicit, t, true)); } /** * Inserts the optional template with the given default * value at the given index. * * @param implicit Implicit tag. * @param t Optional sub-template. * @param index Index. */ public void insertOptionalElementAt(Tag implicit, ASN1Template t, int index) { insertElementAt(new Element(implicit, t, true), index); } /** * Adds a sub-template with the given default value to the end * of this SET template. For example, if the ASN.1 included: * *
         * MySet ::= SET {
         *      item        INTEGER DEFAULT (5),
         *      ... }
         * 
* * the "item" element would be added to the MySet template with: * *
         * mySet.addElement(new SubType.Template(), new INTEGER(5));
         * 
* * @param t Sub-template. * @param def Default value. */ public void addElement(ASN1Template t, ASN1Value def) { addElement(new Element(TAG, t, def)); } /** * Inserts the template with the given default * value at the given index. * * @param t Sub-template. * @param def Default value. * @param index Index. */ public void insertElementAt(ASN1Template t, ASN1Value def, int index) { insertElementAt(new Element(null, t, def), index); } /** * Adds a sub-template with the given default value and implicit tag to * the end of this SET template. For example, if the ASN.1 included: * *
         * MySet ::= SET {
         *      item        [0] IMPLICIT INTEGER DEFAULT (5),
         *      ... }
         * 
* * the "item" element would be added to the MySet template with: * *
         * mySet.addElement(new Tag(0), new SubType.Template(), new INTEGER(5));
         * 
* * @param implicit Implicit tag. * @param t Sub-template. * @param def Default value. */ public void addElement(Tag implicit, ASN1Template t, ASN1Value def) { addElement(new Element(implicit, t, def)); } /** * Inserts the template with the given implicit tag and given default * value at the given index. * * @param implicit Implicit tag. * @param t Sub-template. * @param def Default value. * @param index Index. */ public void insertElementAt(Tag implicit, ASN1Template t, ASN1Value def, int index) { insertElementAt(new Element(implicit, t, def), index); } /** * Returns the implicit tag of the item stored at the given index. * May be NULL if no implicit tag was specified. * * @param index Index. * @return Implicit tag. */ public Tag implicitTagAt(int index) { return elements.elementAt(index).getImplicitTag(); } /** * Returns the sub-template stored at the given index. * * @param index Index. * @return Sub-template. */ public ASN1Template templateAt(int index) { return elements.elementAt(index).getTemplate(); } /** * Returns true if the sub-template at the given index * is optional. * * @param index Index. * @return True if sub-template is optional. */ public boolean isOptionalAt(int index) { return elements.elementAt(index).isOptional(); } private boolean isRepeatableAt(int index) { return elements.elementAt(index).isRepeatable(); } /** * Returns the default value for the sub-template at the given index. * May return NULL if no default value was specified. * * @param index Index. * @return Default value. */ public ASN1Value defaultAt(int index) { return elements.elementAt(index).getDefault(); } /** * @return The number of elements in the SET. */ public int size() { return elements.size(); } public void removeAllElements() { elements.removeAllElements(); } public void removeElementAt(int index) { elements.removeElementAt(index); } private Tag getTag() { return SET.TAG; } /** * Determines whether the given tag satisfies this template. * * @param tag Tag. * @return True if tag satisfies this template. */ @Override public boolean tagMatch(Tag tag) { return (tag.equals(SET.TAG)); } /** * Decodes the input stream into a SET value. * * @param istream Input stream. * @return Decoded SET value. */ @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(getTag(), istream); } /** * Decodes the input stream into a SET value with the given implicit * tag. * * @param tag Implicit tag. * @param istream Input stream. * @return Decoded SET value. */ @Override public ASN1Value decode(Tag tag, InputStream istream) throws IOException, InvalidBERException { try { ASN1Header header = new ASN1Header(istream); header.validate(tag, Form.CONSTRUCTED); // remainingContent will be -1 for indefinite length encoding long remainingContent = header.getContentLength(); SET set = new SET(); ASN1Header lookAhead; boolean[] found = new boolean[elements.size()]; // while content remains, try to decode it while (remainingContent > 0 || remainingContent == -1) { // find out about the next item lookAhead = ASN1Header.lookAhead(istream); // if we found the end-of-content marker, we're done if (lookAhead.isEOC()) { if (remainingContent != -1) { throw new InvalidBERException("Unexpected end-of-content" + "marker"); } lookAhead = new ASN1Header(istream); break; } // Find the element with the matching tag int index = findElementByTag(lookAhead.getTag()); if (index == -1) { // element not found throw new InvalidBERException("Unexpected Tag in SET: " + lookAhead.getTag()); } Element e = elements.elementAt(index); if (found[index] && !e.isRepeatable()) { // element already found, and it's not repeatable throw new InvalidBERException("Duplicate Tag in SET: " + lookAhead.getTag()); } // mark this element as found found[index] = true; // Decode this element ASN1Template t = e.getTemplate(); ASN1Value val; try (CountingStream countstream = new CountingStream(istream)) { if (e.getImplicitTag() == null) { val = t.decode(countstream); } else { val = t.decode(e.getImplicitTag(), countstream); } // Decrement remaining count long len = countstream.getNumRead(); if (remainingContent != -1) { if (remainingContent < len) { // this item went past the end of the SET throw new InvalidBERException("Item went " + (len - remainingContent) + " bytes past the end of" + " the SET"); } remainingContent -= len; } } // Store this element in the SET SET.Element se; if (e.getImplicitTag() == null) { // no implicit tag se = new SET.Element(val); } else { // there is an implicit tag se = new SET.Element(e.getImplicitTag(), val); } set.addElement(se); } // We check for this after we read in each item, so this shouldn't // happen assert (remainingContent == 0 || remainingContent == -1); // Deal with elements that weren't present. int size = elements.size(); for (int i = 0; i < size; i++) { if (!found[i]) { if (isOptionalAt(i) || isRepeatableAt(i)) { // no problem } else if (defaultAt(i) != null) { set.addElement(new SET.Element(defaultAt(i))); } else { throw new InvalidBERException("Field not found in SET"); } } } return set; } catch (InvalidBERException e) { throw new InvalidBERException(e, "SET"); } } /** * Returns the index in the vector of the type with this tag and class, * or -1 if not found. * lame linear search - but we're dealing with small numbers of elements, * so it's probably not worth it to use a hashtable * * @param tag Tag. */ private int findElementByTag(Tag tag) { int size = elements.size(); for (int i = 0; i < size; i++) { Element e = elements.elementAt(i); if (e.tagMatch(tag)) { // match! return i; } } // no match return -1; } /** * An element of a SET template. */ public static class Element { public Element(Tag implicitTag, ASN1Template type, boolean optional) { this.type = type; defaultVal = null; this.optional = optional; this.implicitTag = implicitTag; } public Element(Tag implicitTag, ASN1Template type, ASN1Value defaultVal) { this.type = type; this.defaultVal = defaultVal; optional = false; this.implicitTag = implicitTag; } // Repeatability is used for SET OF. It is package private. private boolean repeatable; void makeRepeatable() { repeatable = true; } boolean isRepeatable() { return repeatable; } private boolean optional; public boolean isOptional() { return optional; } private Tag implicitTag = null; public Tag getImplicitTag() { return implicitTag; } /** * Determines whether the given tag satisfies this SET element. * * @param tag Tag. * @return True if tag satisfies SET. */ public boolean tagMatch(Tag tag) { if (implicitTag != null) { return (implicitTag.equals(tag)); } else { return type.tagMatch(tag); } } private ASN1Template type; /** * @return The template for this element. */ public ASN1Template getTemplate() { return type; } private ASN1Value defaultVal = null; /** * Returns the default value for this element, if one exists. * Otherwise, returns null. * * @return Default value. */ public ASN1Value getDefault() { return defaultVal; } } } // End of SET.Template /** * A Template for decoding SET OF values. * Use this if you have a SIZE qualifier on your SET OF. * The SET will consume as many instances of type as it can, rather than * stopping after the first one. This is equivalent to SIZE (0..MAX). * If you need something more restrictive, you can look at what gets parsed * and decide whether it's OK or not yourself. */ public static class OF_Template implements ASN1Template { private Template template; // a normal SET template /** * Creates an OF_Template with the given type. For example: * *
         * MySet ::= SET OF INTEGER;
         * 
* * A MySet template would be constructed with: * *
         * SET.OF_Template mySetTemplate = new SET.OF_Template(new INTEGER.Template());
         * 
* * @param type Type. */ public OF_Template(ASN1Template type) { template = new Template(); Template.Element el = new Template.Element(null, type, false); el.makeRepeatable(); template.addElement(el); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } /** * Decodes a SET OF from its BER encoding. */ @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return template.decode(istream); } /** * Decodes a SET OF with an implicit tag from its BER * encoding. */ @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { return template.decode(implicitTag, istream); } } // Test driver for SET public static void main(String args[]) { try { if (args.length > 0) { Template t = new SET.Template(); t.addElement(new Tag(0), new INTEGER.Template()); t.addElement(new Tag(3), new INTEGER.Template()); t.addOptionalElement(new Tag(4), new INTEGER.Template()); t.addElement(new Tag(5), new INTEGER.Template(), new INTEGER(67)); t.addElement(new Tag(29), new BOOLEAN.Template()); t.addElement(new Tag(30), new BOOLEAN.Template(), new BOOLEAN(false)); t.addElement(new Tag(1), new INTEGER.Template()); t.addElement(new Tag(2), new INTEGER.Template()); SET st; FileInputStream fin = new FileInputStream(args[0]); try (BufferedInputStream is = new BufferedInputStream(fin)) { st = (SET) t.decode(is); } for (int i = 0; i < st.size(); i++) { ASN1Value v = st.elementAt(i); if (v instanceof INTEGER) { INTEGER in = (INTEGER) st.elementAt(i); System.out.println("INTEGER: " + in); } else if (v instanceof BOOLEAN) { BOOLEAN bo = (BOOLEAN) st.elementAt(i); System.out.println("BOOLEAN: " + bo); } else { System.out.println("Unknown value"); } } } else { SET s = new SET(); s.addElement(new Tag(0), new INTEGER(255)); s.addElement(new Tag(29), new BOOLEAN(true)); s.addElement(new Tag(1), new INTEGER(-322)); s.addElement(new Tag(2), new INTEGER(0)); s.addElement(new Tag(3), new INTEGER("623423948273")); s.encode(System.out); } } catch (Exception e) { e.printStackTrace(); } } } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/Tag.java000066400000000000000000000120621412550063600222270ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; /** * Represents an ASN.1 Tag. A tag consists of a class and a number. */ public class Tag { private long num; /** * @return The tag number. */ public long getNum() { return num; } private Class tClass; /** * @return The tag class. */ public Class getTagClass() { return tClass; } /** * A tag class. */ public static final Class UNIVERSAL = Class.UNIVERSAL; /** * A tag class. */ public static final Class APPLICATION = Class.APPLICATION; /** * A tag class. */ public static final Class CONTEXT_SPECIFIC = Class.CONTEXT_SPECIFIC; /** * A tag class. */ public static final Class PRIVATE = Class.PRIVATE; /** * The end-of-contents marker for indefinite length encoding. * It is encoded the same as an ASN.1 header whose tag is [UNIVERSAL 0]. */ public static final Tag END_OF_CONTENTS = new Tag(UNIVERSAL, 0); /** * An alias for END_OF_CONTENTS. */ public static final Tag EOC = END_OF_CONTENTS; /** * Creates a tag with the given class and number. * * @param clazz The class of the tag. * @param num The tag number. */ public Tag(Class clazz, long num) { tClass = clazz; this.num = num; } /** * Creates a CONTEXT-SPECIFIC tag with the given tag number. * * @param num The tag number. */ public Tag(long num) { this(Class.CONTEXT_SPECIFIC, num); } /////////////////////////////////////////////////////////////////////// // Tag Instances // // Since grabbing a context-specific tag is a very common operation, // let's make singletons of the most frequently used tags. /////////////////////////////////////////////////////////////////////// private static final int numTagInstances = 10; private static Tag tagInstances[] = new Tag[numTagInstances]; static { for (int i = 0; i < numTagInstances; i++) { tagInstances[i] = new Tag(i); } } /** * Returns an instance of a context-specific tag with the given number. * The returned instance may be singleton. It is usually more efficient to * call this method than create your own context-specific tag. * * @param num Number. * @return Tag. */ public static Tag get(long num) { if (num >= 0 && num < numTagInstances) { return tagInstances[(int) num]; } else { return new Tag(num); } } @Override public int hashCode() { return (tClass.toInt() * 131) + (int) num; } /** * Compares two tags for equality. Tags are equal if they have * the same class and tag number. * * @param obj Tag. * @return True if equal. */ @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (!(obj instanceof Tag)) { return false; } Tag t = (Tag) obj; if (num == t.num && tClass == t.tClass) { return true; } else { return false; } } /** * Returns a String representation of the tag. For example, a tag * whose class was UNIVERSAL and whose number was 16 would return * "UNIVERSAL 16". */ @Override public String toString() { return tClass + " " + num; } /** * An enumeration of the ASN.1 tag classes. */ public static class Class { private Class() { } private Class(int enc, String name) { encoding = enc; this.name = name; } private int encoding; private String name; public static final Class UNIVERSAL = new Class(0, "UNIVERSAL"); public static final Class APPLICATION = new Class(1, "APPLICATION"); public static final Class CONTEXT_SPECIFIC = new Class(2, "CONTEXT-SPECIFIC"); public static final Class PRIVATE = new Class(3, "PRIVATE"); public int toInt() { return encoding; } @Override public String toString() { return name; } /** * @param i Tag encoding. * @return Tag class. * @exception InvalidBERException If the given int does not correspond * to any tag class. */ public static Class fromInt(int i) throws InvalidBERException { if (i == 0) { return UNIVERSAL; } else if (i == 1) { return APPLICATION; } else if (i == 2) { return CONTEXT_SPECIFIC; } else if (i == 3) { return PRIVATE; } else { throw new InvalidBERException("Invalid tag class: " + i); } } } } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/TeletexString.java000066400000000000000000000054301412550063600243160ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.CharConversionException; /** * The ASN.1 type TeletexString. */ public class TeletexString extends CharacterString { public static final Tag TAG = new Tag(Tag.UNIVERSAL, 20); @Override public Tag getTag() { return TAG; } public TeletexString(char[] chars) throws CharConversionException { super(chars); } public TeletexString(String s) throws CharConversionException { super(s); } @Override CharConverter getCharConverter() { return new TeletexConverter(); } /** * Returns a singleton instance of the decoding template for this class. * * @return Template. */ public static Template getTemplate() { return templateInstance; } private static final Template templateInstance = new Template(); // nested class public static class Template extends CharacterString.Template { @Override protected Tag getTag() { return TAG; } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override protected CharConverter getCharConverter() { return new TeletexConverter(); } @Override protected CharacterString generateInstance(char[] bytes) throws CharConversionException { return new TeletexString(bytes); } @Override protected String typeName() { return "TeletexString"; } } // end of Template private static class TeletexConverter implements CharConverter { @Override public char[] byteToChar(byte[] bytes, int offset, int len) throws CharConversionException { char[] chars = new char[len]; int b; int c; for (b = offset, c = 0; c < len; b++, c++) { chars[c] = (char) (bytes[b] & 0xff); } return chars; } @Override public byte[] charToByte(char[] chars, int offset, int len) throws CharConversionException { byte[] bytes = new byte[len]; int b; int c; for (b = 0, c = offset; b < len; b++, c++) { if ((chars[c] & 0xff00) != 0) { throw new CharConversionException("Invalid character for" + " TeletexString"); } bytes[b] = (byte) (chars[c] & 0xff); } return bytes; } } } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/TimeBase.java000066400000000000000000000225441412550063600232130ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Calendar; import java.util.Date; import java.util.TimeZone; public abstract class TimeBase implements ASN1Value { public static final Form FORM = Form.PRIMITIVE; @Override abstract public Tag getTag(); private Date date; public Date toDate() { return date; } abstract protected boolean isUTC(); public TimeBase(Date date) { this.date = date; } @Override public void encode(OutputStream ostream) throws IOException { encode(getTag(), ostream); } /** * Write the DER-encoding of this TimeBase. */ @Override public void encode(Tag implicit, OutputStream ostream) throws IOException { if (isUTC()) { // length will always be 13 (new ASN1Header(implicit, FORM, 13)).encode(ostream); } else { // length will always be 15 (new ASN1Header(implicit, FORM, 15)).encode(ostream); } int i = 0, val; // DER-encoding mandates GMT time zone Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); cal.setTime(date); if (isUTC()) { val = cal.get(Calendar.YEAR); ostream.write(((val % 100) / 10) + '0'); ostream.write((val % 10) + '0'); } else { val = cal.get(Calendar.YEAR); ostream.write(((val % 10000) / 1000) + '0'); ostream.write(((val % 1000) / 100) + '0'); ostream.write(((val % 100) / 10) + '0'); ostream.write((val % 10) + '0'); } val = cal.get(Calendar.MONTH) + 1; assert (val >= 1 && val <= 12); ostream.write((val / 10) + '0'); ostream.write((val % 10) + '0'); val = cal.get(Calendar.DAY_OF_MONTH); assert (val >= 1 && val <= 31); ostream.write((val / 10) + '0'); ostream.write((val % 10) + '0'); val = cal.get(Calendar.HOUR_OF_DAY); assert (val >= 0 && val <= 23); ostream.write((val / 10) + '0'); ostream.write((val % 10) + '0'); val = cal.get(Calendar.MINUTE); assert (val >= 0 && val <= 59); ostream.write((val / 10) + '0'); ostream.write((val % 10) + '0'); val = cal.get(Calendar.SECOND); assert (val >= 0 && val <= 59); ostream.write((val / 10) + '0'); ostream.write((val % 10) + '0'); ostream.write('Z'); } public abstract static class Template { protected abstract boolean isUTC(); protected abstract Tag getTag(); protected abstract TimeBase generateInstance(Date date); public boolean tagMatch(Tag tag) { return getTag().equals(tag); } public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(getTag(), istream); } public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { PrintableString.Template pst = new PrintableString.Template(); PrintableString ps = (PrintableString) pst.decode(implicitTag, istream); char[] chars = ps.toCharArray(); int i = 0; int year, month, day, hour, minute, second, hourOff, minOff; ////////////////////////////////////////// // Get year // if (isUTC()) { checkBounds(i, 2, chars.length); year = (chars[i] - '0') * 10; year += chars[i + 1] - '0'; // Y2K HACK!!!!! But this is what the spec says to do. // The range is 1970 to 2069 if (year < 70) { year += 2000; } else { year += 1900; } i += 2; } else { checkBounds(i, 4, chars.length); year = (chars[i] - '0') * 1000; year += (chars[i + 1] - '0') * 100; year += (chars[i + 2] - '0') * 10; year += (chars[i + 3] - '0'); checkRange(year, 0, 9999, "year"); i += 4; } ////////////////////////////////////////// // get month // month = 0; checkBounds(i, 2, chars.length); month = (chars[i] - '0') * 10; month += chars[i + 1] - '0'; checkRange(month, 1, 12, "month"); month--; // Java months start at 0 i += 2; ////////////////////////////////////////// // get day // checkBounds(i, 2, chars.length); day = (chars[i] - '0') * 10; day += chars[i + 1] - '0'; checkRange(day, 1, 31, "day"); i += 2; ////////////////////////////////////////// // get hour // checkBounds(i, 2, chars.length); hour = (chars[i] - '0') * 10; hour += chars[i + 1] - '0'; checkRange(hour, 0, 23, "hour"); i += 2; ////////////////////////////////////////// // get minute // checkBounds(i, 2, chars.length); minute = (chars[i] - '0') * 10; minute += chars[i + 1] - '0'; checkRange(minute, 0, 59, "minute"); i += 2; ////////////////////////////////////////// // get second, if it's there // if (i < chars.length && chars[i] >= '0' && chars[i] <= '9') { checkBounds(i, 2, chars.length); second = (chars[i] - '0') * 10; second += chars[i + 1] - '0'; checkRange(second, 0, 59, "second"); i += 2; } else { second = 0; } ////////////////////////////////////////// // Skip milliseconds for GeneralizedTime. There are no // milliseconds in UTCTime. // if (!isUTC()) { while (i < chars.length && chars[i] != '+' && chars[i] != '-' && chars[i] != 'Z') { i++; } } ////////////////////////////////////////// // get time zone // TimeZone tz; if (i < chars.length) { checkBounds(i, 1, chars.length); if (chars[i] == '+' || chars[i] == '-') { checkBounds(i + 1, 4, chars.length); hourOff = (chars[i + 1] - '0') * 10; hourOff += chars[i + 2] - '0'; minOff = (chars[i + 3] - '0') * 10; minOff += chars[i + 4] - '0'; checkRange(hourOff, 0, 23, "hour offset"); checkRange(minOff, 0, 59, "minute offset"); if (chars[i] == '-') { hourOff = -hourOff; minOff = -minOff; } i += 5; tz = (TimeZone) TimeZone.getTimeZone("GMT").clone(); tz.setRawOffset(((hourOff * 60) + minOff) * 60 * 1000); } else if (chars[i] == 'Z') { i += 1; hourOff = minOff = 0; tz = (TimeZone) TimeZone.getTimeZone("GMT").clone(); } else { throw new InvalidBERException("Invalid character " + chars[i]); } } else { if (isUTC()) { // Only UTC requires timezone throw new InvalidBERException("no timezone specified for" + " UTCTime"); } // No timezone specified, use local time. // This is generally a bad idea, because who knows what the // local timezone is? But the spec allows it. tz = TimeZone.getDefault(); } // make sure we ate all the characters, there were no stragglers // at the end if (i != chars.length) { throw new InvalidBERException("Extra characters at end"); } // Create a calendar object from the date and time zone. Calendar cal = Calendar.getInstance(tz); cal.set(year, month, day, hour, minute, second); return generateInstance(cal.getTime()); } private static void checkRange(int val, int low, int high, String field) throws InvalidBERException { if (val < low || val > high) { throw new InvalidBERException("Invalid " + field); } } private static void checkBounds(int index, int increment, int bound) throws InvalidBERException { if (index + increment > bound) { throw new InvalidBERException("Too few characters in " + "TimeBase"); } } } } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/UTCTime.java000066400000000000000000000023461412550063600227720ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.util.Date; public class UTCTime extends TimeBase { public static final Tag TAG = new Tag(Tag.UNIVERSAL, 23); @Override public Tag getTag() { return TAG; } public UTCTime(Date date) { super(date); } @Override protected boolean isUTC() { return true; } private static final UTCTime.Template templateInstance = new UTCTime.Template(); public static UTCTime.Template getTemplate() { return templateInstance; } public static class Template extends TimeBase.Template implements ASN1Template { @Override protected Tag getTag() { return TAG; } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override protected boolean isUTC() { return true; } @Override protected TimeBase generateInstance(Date date) { return new UTCTime(date); } } } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/UTF8String.java000066400000000000000000000056551412550063600234430ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.CharConversionException; import java.io.UnsupportedEncodingException; public class UTF8String extends CharacterString { public UTF8String(char[] chars) throws CharConversionException { super(chars); } public UTF8String(String s) throws CharConversionException { super(s); } @Override CharConverter getCharConverter() { return new UTF8Converter(); } public static final Tag TAG = new Tag(Tag.UNIVERSAL, 12); public static final Form FORM = Form.PRIMITIVE; @Override public Tag getTag() { return TAG; } private static final Template templateInstance = new Template(); /** * Returns a singleton instance of UTF8String.Template. This is more * efficient than creating a new UTF8String.Template. * * @return Template. */ public static Template getTemplate() { return templateInstance; } // nested class public static class Template extends CharacterString.Template { @Override protected Tag getTag() { return TAG; } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override protected CharConverter getCharConverter() { return new UTF8Converter(); } @Override protected CharacterString generateInstance(char[] chars) throws CharConversionException { return new UTF8String(chars); } @Override protected String typeName() { return "UTF8String"; } } private static class UTF8Converter implements CharConverter { @Override public char[] byteToChar(byte[] bytes, int offset, int len) throws CharConversionException { try { String s = new String(bytes, offset, len, "UTF8"); return s.toCharArray(); } catch (UnsupportedEncodingException e) { String err = "Unable to find UTF8 encoding mechanism"; throw (CharConversionException) new CharConversionException(err).initCause(e); } } @Override public byte[] charToByte(char[] chars, int offset, int len) throws CharConversionException { try { String s = new String(chars, offset, len); return s.getBytes("UTF8"); } catch (UnsupportedEncodingException e) { String err = "Unable to find UTF8 encoding mechanism"; throw (CharConversionException) new CharConversionException(err).initCause(e); } } } // end of char converter } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/UniversalString.java000066400000000000000000000155011412550063600246540ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.asn1; import java.io.ByteArrayOutputStream; import java.io.CharArrayWriter; import java.io.CharConversionException; /** * A UCS4 string. */ public class UniversalString extends CharacterString { public static final Tag TAG = new Tag(Tag.UNIVERSAL, 28); @Override public Tag getTag() { return TAG; } public UniversalString(char[] chars) throws CharConversionException { super(chars); } public UniversalString(String s) throws CharConversionException { super(s); } @Override CharConverter getCharConverter() { return new UniversalConverter(); } /** * Returns a singleton instance of the decoding template for this class. * * @return Template. */ public static Template getTemplate() { return templateInstance; } private static final Template templateInstance = new Template(); // nested class public static class Template extends CharacterString.Template { @Override protected Tag getTag() { return TAG; } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override protected CharConverter getCharConverter() { return new UniversalConverter(); } @Override protected CharacterString generateInstance(char[] chars) throws CharConversionException { return new UniversalString(chars); } @Override protected String typeName() { return "UniversalString"; } } // end of Template /** * A class for converting between Unicode and UCS4. */ private static class UniversalConverter implements CharConverter { // This is the maximum a UCS4 character can be if it has // straight Unicode inside it. public static final int MAX_UNICODE = 0x0000ffff; // This is the maximum a UCS4 character can be if it is UTF-16 // encoded. UTF-16 encoding allows UCS4 chars to be stored across // two Unicode chars. public static final int MAX_UTF16 = 0x0010ffff; // This Unicode character is used to represent an unknown character // in some other encoding. We use it for UCS4 characters that // are not a part of normal Unicode and also cannot be encoded // across two Unicode chars with UTF-16. public static final char REPLACEMENT_CHAR = 0xfffd; // This is the base for UCS4 characters that can be mapped with UTF16. public static final int UTF16_BASE = 0x00100000; // In UTF16 encoding, each Unicode character has 10 bits of // information. public static final int HALF_SHIFT = 10; // The lowest 10 bits public static final int HALF_MASK = 0x3ff; public static final int UTF16_HIGH_START = 0xd800; public static final int UTF16_HIGH_END = 0xdcff; public static final int UTF16_LOW_START = 0xdc00; public static final int UTF16_LOW_END = 0xdfff; /** * Turns big-endian UCS4 characters into Unicode Java characters */ @Override public char[] byteToChar(byte[] bytes, int offset, int len) throws CharConversionException { // Each UCS4 character is 4 bytes. Most UCS4 characters will // map to one Unicode character. The exception is UTF-16 // characters, which map to two Unicode characters. CharArrayWriter out = new CharArrayWriter(len / 4); int end = offset + len; while (offset < end) { // eat 4 bytes and make a UCS4 char if (end - offset < 4) { throw new CharConversionException("input exhausted"); } int ucs4 = (bytes[offset++] & 0xff) << 24; ucs4 += (bytes[offset++] & 0xff) << 16; ucs4 += (bytes[offset++] & 0xff) << 8; ucs4 += bytes[offset++] & 0xff; // convert UCS4 to Unicode if (ucs4 <= MAX_UNICODE) { // Unicode is a subset of UCS4, and this char is // in the common subset. Just chop off the unused top // two bytes. out.write(ucs4 & 0xffff); } else if (ucs4 <= MAX_UTF16) { // This UCS4 char is not in Unicode, but can be encoded // into two Unicode chars using UTF16. ucs4 -= UTF16_BASE; out.write((ucs4 >>> HALF_SHIFT) + UTF16_HIGH_START); out.write((ucs4 & HALF_MASK) + UTF16_LOW_START); } else { // This character is not in Unicode or UTF16. We can't // provide a suitable translation, so use the Unicode // replacement char. out.write(REPLACEMENT_CHAR); } } return out.toCharArray(); } // Convert Unicode chars to UCS4 chars @Override public byte[] charToByte(char[] chars, int offset, int len) throws CharConversionException { ByteArrayOutputStream out = new ByteArrayOutputStream(len * 4); int end = offset + len; while (offset < end) { char c = chars[offset++]; int ucs4; if (c >= UTF16_HIGH_START && c <= UTF16_HIGH_END) { // This is the beginning of a UTF16 char if (offset == end) { throw new CharConversionException("input exhausted"); } char low = chars[offset++]; // make sure the next char is the low half of a UTF16 char if (low < UTF16_LOW_START || low > UTF16_LOW_END) { throw new CharConversionException("UTF16 high " + "character not followed by a UTF16 low character"); } ucs4 = UTF16_BASE; ucs4 += (c - UTF16_HIGH_START) << HALF_SHIFT; ucs4 += low - UTF16_LOW_START; } else { // this is a normal Unicode char ucs4 = (c & 0x0000ffff); } out.write((ucs4 & 0xff000000) >>> 24); out.write((ucs4 & 0x00ff0000) >>> 16); out.write((ucs4 & 0x0000ff00) >>> 8); out.write((ucs4 & 0x000000ff)); } return out.toByteArray(); } } } jss-5.0.0/src/main/java/org/mozilla/jss/asn1/package.html000066400000000000000000000004441412550063600231330ustar00rootroot00000000000000 ASN.1 structures, BER decoding, and DER encoding. jss-5.0.0/src/main/java/org/mozilla/jss/crypto/000077500000000000000000000000001412550063600213265ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/crypto/Algorithm.c000066400000000000000000000307231412550063600234250ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include #include "Algorithm.h" static PRStatus getAlgInfo(JNIEnv *env, jobject alg, JSS_AlgInfo *info); /* Helpers to handle differences in NSS versions. */ #ifndef CKM_AES_CMAC #define CKM_AES_CMAC CKM_INVALID_MECHANISM #endif #ifndef CKM_SP800_108_COUNTER_KDF /* All added at the same time. */ #define CKM_SP800_108_COUNTER_KDF CKM_INVALID_MECHANISM #define CKM_SP800_108_FEEDBACK_KDF CKM_INVALID_MECHANISM #define CKM_SP800_108_DOUBLE_PIPELINE_KDF CKM_INVALID_MECHANISM #define CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA CKM_INVALID_MECHANISM #define CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA CKM_INVALID_MECHANISM #define CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA CKM_INVALID_MECHANISM #endif #define OI(x) \ { \ siDEROID, (unsigned char *)x, sizeof x \ } #define OD(oid, tag, desc, mech, ext) \ { \ OI(oid) \ , tag, desc, mech, ext \ } #define ODN(oid, desc) \ { \ OI(oid) \ , 0, desc, CKM_INVALID_MECHANISM, INVALID_CERT_EXTENSION \ } #define OIDT static const unsigned char /* USGov algorithm OID space: { 2 16 840 1 101 } */ #define USGOV 0x60, 0x86, 0x48, 0x01, 0x65 #define NISTALGS USGOV, 3, 4 #define AES NISTALGS, 1 /* AES_KEY_WRAP_KWP oids */ OIDT aes128_KEY_WRAP_KWP[] = { AES, 8 }; OIDT aes192_KEY_WRAP_KWP[] = { AES, 28 }; OIDT aes256_KEY_WRAP_KWP[] = { AES, 48 }; /* ------------------------------------------------------------------- */ static const SECOidData oids[] = { /* AES_KEY_WRAP_KWP oids */ OD(aes128_KEY_WRAP_KWP,0,"AES-128 Key Wrap Kwp", CKM_AES_KEY_WRAP_KWP, INVALID_CERT_EXTENSION), OD(aes192_KEY_WRAP_KWP,0,"AES-192 Key Wrap Kwp", CKM_AES_KEY_WRAP_KWP, INVALID_CERT_EXTENSION), OD(aes256_KEY_WRAP_KWP,0,"AES-256 Key Wrap Kwp", CKM_AES_KEY_WRAP_KWP, INVALID_CERT_EXTENSION), }; static const unsigned int numOids = (sizeof oids) / (sizeof oids[0]); static SECOidTag newOIDTags[3]; /*********************************************************************** ** ** Algorithm indices. This must be kept in sync with the algorithm ** tags in the Algorithm class. ** We only store CKMs as a last resort if there is no corresponding ** SEC_OID. **/ JSS_AlgInfo JSS_AlgTable[NUM_ALGS] = { /* 0 */ {SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION, SEC_OID_TAG}, /* 1 */ {SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION, SEC_OID_TAG}, /* 2 */ {SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION, SEC_OID_TAG}, /* 3 */ {SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST, SEC_OID_TAG}, /* 4 */ {SEC_OID_PKCS1_RSA_ENCRYPTION, SEC_OID_TAG}, /* 5 */ {CKM_RSA_PKCS_KEY_PAIR_GEN, PK11_MECH}, /* 6 */ {CKM_DSA_KEY_PAIR_GEN, PK11_MECH}, /* 7 */ {SEC_OID_ANSIX9_DSA_SIGNATURE, SEC_OID_TAG}, /* 8 */ {SEC_OID_RC4, SEC_OID_TAG}, /* 9 */ {SEC_OID_DES_ECB, SEC_OID_TAG}, /* 10 */ {SEC_OID_DES_CBC, SEC_OID_TAG}, /* 11 */ {CKM_DES_CBC_PAD, PK11_MECH}, /* 12 */ {CKM_DES3_ECB, PK11_MECH}, /* 13 */ {SEC_OID_DES_EDE3_CBC, SEC_OID_TAG}, /* 14 */ {CKM_DES3_CBC_PAD, PK11_MECH}, /* 15 */ {CKM_DES_KEY_GEN, PK11_MECH}, /* 16 */ {CKM_DES3_KEY_GEN, PK11_MECH}, /* 17 */ {CKM_RC4_KEY_GEN, PK11_MECH}, /* 18 */ {SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC, SEC_OID_TAG}, /* 19 */ {SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC, SEC_OID_TAG}, /* 20 */ {SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC, SEC_OID_TAG}, /* 21 */ {SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4, SEC_OID_TAG}, /* 22 */ {SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4, SEC_OID_TAG}, /* 23 */ {SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC, SEC_OID_TAG}, /* 24 */ {SEC_OID_MD2, SEC_OID_TAG}, /* 25 */ {SEC_OID_MD5, SEC_OID_TAG}, /* 26 */ {SEC_OID_SHA1, SEC_OID_TAG}, /* 27 */ {CKM_SHA_1_HMAC, PK11_MECH}, /* 28 */ {SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC, SEC_OID_TAG}, /* 29 */ {SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC, SEC_OID_TAG}, /* 30 */ {SEC_OID_RC2_CBC, SEC_OID_TAG}, /* 31 */ {CKM_PBA_SHA1_WITH_SHA1_HMAC, PK11_MECH}, /* 32 */ {CKM_AES_KEY_GEN, PK11_MECH}, /* 33 */ {CKM_AES_ECB, PK11_MECH}, /* 34 */ {CKM_AES_CBC, PK11_MECH}, /* 35 */ {CKM_AES_CBC_PAD, PK11_MECH}, /* 36 */ {CKM_RC2_CBC_PAD, PK11_MECH}, /* 37 */ {CKM_RC2_KEY_GEN, PK11_MECH}, /* 38 */ {SEC_OID_SHA256, SEC_OID_TAG}, /* 39 */ {SEC_OID_SHA384, SEC_OID_TAG}, /* 40 */ {SEC_OID_SHA512, SEC_OID_TAG}, /* 41 */ {SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION, SEC_OID_TAG}, /* 42 */ {SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION, SEC_OID_TAG}, /* 43 */ {SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION, SEC_OID_TAG}, /* 44 */ {SEC_OID_ANSIX962_EC_PUBLIC_KEY, SEC_OID_TAG}, /* 45 */ {SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE, SEC_OID_TAG}, /* 46 */ {CKM_EC_KEY_PAIR_GEN, PK11_MECH}, /* 47 */ {SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE, SEC_OID_TAG}, /* 48 */ {SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE, SEC_OID_TAG}, /* 49 */ {SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE, SEC_OID_TAG}, /* 50 */ {SEC_OID_HMAC_SHA256, SEC_OID_TAG}, /* 51 */ {SEC_OID_HMAC_SHA384, SEC_OID_TAG}, /* 52 */ {SEC_OID_HMAC_SHA512, SEC_OID_TAG}, /* 53 */ {SEC_OID_PKCS5_PBKDF2, SEC_OID_TAG}, /* 54 */ {SEC_OID_PKCS5_PBES2, SEC_OID_TAG}, /* 55 */ {SEC_OID_PKCS5_PBMAC1, SEC_OID_TAG}, /* 56 */ {SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST, SEC_OID_TAG}, /* 57 */ {CKM_NSS_AES_KEY_WRAP, PK11_MECH}, /* 58 */ {CKM_NSS_AES_KEY_WRAP_PAD, PK11_MECH}, /* 59 */ {SEC_OID_AES_128_ECB, SEC_OID_TAG}, /* 60 */ {SEC_OID_AES_128_CBC, SEC_OID_TAG}, /* 61 */ {SEC_OID_AES_192_ECB, SEC_OID_TAG}, /* 62 */ {SEC_OID_AES_192_CBC, SEC_OID_TAG}, /* 63 */ {SEC_OID_AES_256_ECB, SEC_OID_TAG}, /* 64 */ {SEC_OID_AES_256_CBC, SEC_OID_TAG}, /* the CKM_AES_KEY_WRAP_* have different defs than CKM_NSS_AES_KEY_WRAP_* */ /* 65 */ {CKM_AES_KEY_WRAP, PK11_MECH}, /* 66 */ {CKM_AES_KEY_WRAP_PAD, PK11_MECH}, /* 67 */ {CKM_SHA256_HMAC, PK11_MECH}, /* 68 */ {CKM_SHA384_HMAC, PK11_MECH}, /* 69 */ {CKM_SHA512_HMAC, PK11_MECH}, /* CKM_AES_CMAC is new to NSS; some implementations might not yet have it. */ /* 70 */ {CKM_AES_CMAC, PK11_MECH}, /* CKM_GENERIC_SECRET_KEY_GEN stub for additional keys. */ /* 71 */ {CKM_GENERIC_SECRET_KEY_GEN, PK11_MECH}, /* CKM_SP800_108_* and CKM_NSS_SP800_108_*_DERIVE_DATA are new to NSS; some * implementations might not yet have it. */ /* 72 */ {CKM_SP800_108_COUNTER_KDF, PK11_MECH}, /* 73 */ {CKM_SP800_108_FEEDBACK_KDF, PK11_MECH}, /* 74 */ {CKM_SP800_108_DOUBLE_PIPELINE_KDF, PK11_MECH}, /* 75 */ {CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA, PK11_MECH}, /* 76 */ {CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA, PK11_MECH}, /* 77 */ {CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA, PK11_MECH}, /* 78 */ {SEC_OID_PKCS1_RSA_PSS_SIGNATURE, SEC_OID_TAG}, /* 79 */ {CKM_RSA_PKCS_OAEP, PK11_MECH}, /* 80 */ {CKM_AES_KEY_WRAP_KWP, PK11_MECH}, /* 81 */ {SEC_OID_AES_128_KEY_WRAP_KWP, SEC_OID_TAG}, /* 82 */ {SEC_OID_AES_192_KEY_WRAP_KWP, SEC_OID_TAG}, /* 83 */ {SEC_OID_AES_256_KEY_WRAP_KWP, SEC_OID_TAG}, /* REMEMBER TO UPDATE NUM_ALGS!!! (in Algorithm.h) */ }; /* Fetch and register an oid if it hasn't been done already */ void JSS_cert_fetchOID(SECOidTag *data, const SECOidData *src) { if (*data == SEC_OID_UNKNOWN) { /* AddEntry does the right thing if someone else has already * added the oid. (that is return that oid tag) */ *data = SECOID_AddEntry(src); } } SECStatus JSS_RegisterDynamicOids(void) { unsigned int i; SECStatus rv = SECSuccess; for (i = 0; i < numOids; ++i) { SECOidTag tag = SECOID_AddEntry(&oids[i]); if (tag == SEC_OID_UNKNOWN) { rv = SECFailure; } else { newOIDTags[i] = tag; } } return rv; } /*********************************************************************** * * J S S _ g e t P K 1 1 M e c h F r o m A l g * * INPUTS * alg * An org.mozilla.jss.Algorithm object. Must not be NULL. * RETURNS * CK_MECHANISM_TYPE corresponding to this algorithm, or * CKM_INVALID_MECHANISM if none exists. */ CK_MECHANISM_TYPE JSS_getPK11MechFromAlg(JNIEnv *env, jobject alg) { JSS_AlgInfo info; if( getAlgInfo(env, alg, &info) != PR_SUCCESS) { return CKM_INVALID_MECHANISM; } if( info.type == PK11_MECH ) { return (CK_MECHANISM_TYPE) info.val; } else { PR_ASSERT( info.type == SEC_OID_TAG ); return PK11_AlgtagToMechanism( (SECOidTag) info.val); } } /*********************************************************************** * * J S S _ g e t O i d T a g F r o m A l g * * INPUTS * alg * An org.mozilla.jss.Algorithm object. Must not be NULL. * RETURNS * SECOidTag corresponding to this algorithm, or SEC_OID_UNKNOWN * if none was found. */ SECOidTag JSS_getOidTagFromAlg(JNIEnv *env, jobject alg) { JSS_AlgInfo info; if( getAlgInfo(env, alg, &info) != PR_SUCCESS) { return SEC_OID_UNKNOWN; } if( info.type == SEC_OID_TAG ) { return (SECOidTag) info.val; } else { PR_ASSERT( info.type == PK11_MECH ); /* We only store things as PK11 mechanisms as a last resort if * there is no corresponding sec oid tag. */ return SEC_OID_UNKNOWN; } } /*********************************************************************** * * J S S _ g e t A l g I n d e x * * INPUTS * alg * An org.mozilla.jss.Algorithm object. Must not be NULL. * RETURNS * The index obtained from the algorithm, or -1 if an exception was * thrown. */ static jint getAlgIndex(JNIEnv *env, jobject alg) { jclass algClass; jint index=-1; jfieldID indexField; PR_ASSERT(env!=NULL && alg!=NULL); algClass = (*env)->GetObjectClass(env, alg); #ifdef DEBUG /* Make sure this really is an Algorithm. */ { jclass realClass = ((*env)->FindClass(env, ALGORITHM_CLASS_NAME)); PR_ASSERT( (*env)->IsInstanceOf(env, alg, realClass) ); } #endif indexField = (*env)->GetFieldID( env, algClass, OID_INDEX_FIELD_NAME, OID_INDEX_FIELD_SIG); if(indexField==NULL) { ASSERT_OUTOFMEM(env); goto finish; } index = (*env)->GetIntField(env, alg, indexField); PR_ASSERT( (index >= 0) && (index < NUM_ALGS) ); finish: return index; } /*********************************************************************** * * J S S _ g e t E n u m F r o m A l g * * INPUTS * alg * An org.mozilla.jss.Algorithm object. Must not be NULL. * OUTPUTS * info * Pointer to a JSS_AlgInfo which will get the information about * this algorithm, if it is found. Must not be NULL. * RETURNS * PR_SUCCESS if the enum was found, otherwise PR_FAILURE. */ static PRStatus getAlgInfo(JNIEnv *env, jobject alg, JSS_AlgInfo *info) { jint index; PRStatus status = PR_FAILURE; PR_ASSERT(env!=NULL && alg!=NULL && info!=NULL); index = getAlgIndex(env, alg); if( index == -1 ) { goto finish; } *info = JSS_AlgTable[index]; status = PR_SUCCESS; finish: return status; } /*********************************************************************** * * EncryptionAlgorithm.getIVLength * */ JNIEXPORT jint JNICALL Java_org_mozilla_jss_crypto_EncryptionAlgorithm_getIVLength (JNIEnv *env, jobject this) { CK_MECHANISM_TYPE mech; mech = JSS_getPK11MechFromAlg(env, this); if( mech == CKM_INVALID_MECHANISM ) { PR_ASSERT(PR_FALSE); return 0; } else { return PK11_GetIVLength(mech); } } /* * This must be synchronized with SymmetricKey.Usage */ CK_ULONG JSS_symkeyUsage[] = { CKA_ENCRYPT, /* 0 */ CKA_DECRYPT, /* 1 */ CKA_WRAP, /* 2 */ CKA_UNWRAP, /* 3 */ CKA_SIGN, /* 4 */ CKA_VERIFY, /* 5 */ 0UL }; jss-5.0.0/src/main/java/org/mozilla/jss/crypto/Algorithm.h000066400000000000000000000043771412550063600234400ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* These headers must be included before this header: #include #include #include #include */ #ifndef JSS_ALGORITHM_H #define JSS_ALGORITHM_H PR_BEGIN_EXTERN_C typedef enum JSS_AlgType { PK11_MECH, /* CK_MECHANISM_TYPE */ SEC_OID_TAG /* SECOidTag */ } JSS_AlgType; typedef struct JSS_AlgInfoStr { unsigned long val; /* either a CK_MECHANISM_TYPE or a SECOidTag */ JSS_AlgType type; } JSS_AlgInfo; #define NUM_ALGS 84 extern JSS_AlgInfo JSS_AlgTable[]; extern CK_ULONG JSS_symkeyUsage[]; /*********************************************************************** * * J S S _ g e t O i d T a g F r o m A l g * * INPUTS * alg * An org.mozilla.jss.Algorithm object. Must not be NULL. * RETURNS * SECOidTag corresponding to this algorithm, or SEC_OID_UNKNOWN * if none was found. */ SECOidTag JSS_getOidTagFromAlg(JNIEnv *env, jobject alg); /*********************************************************************** * * J S S _ g e t P K 1 1 M e c h F r o m A l g * * INPUTS * alg * An org.mozilla.jss.Algorithm object. Must not be NULL. * RETURNS * CK_MECHANISM_TYPE corresponding to this algorithm, or * CKM_INVALID_MECHANISM if none was found. */ CK_MECHANISM_TYPE JSS_getPK11MechFromAlg(JNIEnv *env, jobject alg); SECStatus JSS_RegisterDynamicOids(void); void SECU_cert_fetchOID(SECOidTag *data, const SECOidData *src); // The following are put here because NSS has not defined these yet #ifndef CKM_AES_KEY_WRAP #define CKM_AES_KEY_WRAP 0x2109 #endif #ifndef CKM_AES_KEY_WRAP_PAD #define CKM_AES_KEY_WRAP_PAD 0x210a #endif #ifndef CKM_AES_KEY_WRAP_KWP #define CKM_AES_KEY_WRAP_KWP 0x210b #endif #ifndef SEC_OID_AES_128_KEY_WRAP_KWP #define SEC_OID_AES_128_KEY_WRAP_KWP (SEC_OID_TOTAL + 0) #endif #ifndef SEC_OID_AES_192_KEY_WRAP_KWP #define SEC_OID_AES_192_KEY_WRAP_KWP (SEC_OID_TOTAL + 1) #endif #ifndef SEC_OID_AES_256_KEY_WRAP_KWP #define SEC_OID_AES_256_KEY_WRAP_KWP (SEC_OID_TOTAL + 2) #endif PR_END_EXTERN_C #endif jss-5.0.0/src/main/java/org/mozilla/jss/crypto/Algorithm.java000066400000000000000000000246141412550063600241260ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.NoSuchAlgorithmException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; /** * Represents a cryptographic algorithm. * * @see EncryptionAlgorithm * @see SignatureAlgorithm */ public class Algorithm { /** * @param oidIndex Index of the oid that this algorithm represents. * @param name A String representation of the Algorithm. */ protected Algorithm(int oidIndex, String name) { this.oidIndex = oidIndex; this.name = name; } /** * @param oidIndex Index of the oid that this algorithm represents. * @param name A String representation of the Algorithm. * @param oid The object identifier for this Algorithm. */ protected Algorithm(int oidIndex, String name, OBJECT_IDENTIFIER oid) { this(oidIndex, name); this.oid = oid; } protected Algorithm(int oidIndex, String name, OBJECT_IDENTIFIER oid, Class paramClass) { this(oidIndex, name, oid); if (paramClass == null) { this.parameterClasses = new Class[0]; } else { this.parameterClasses = new Class[1]; this.parameterClasses[0] = paramClass; } } protected Algorithm(int oidIndex, String name, OBJECT_IDENTIFIER oid, Class[] paramClasses) { this(oidIndex, name, oid); if (paramClasses != null) { this.parameterClasses = paramClasses; } } /** * Returns a String representation of the algorithm. */ @Override public String toString() { return name; } /** * @return The object identifier for this algorithm. * @exception NoSuchAlgorithmException If no OID is registered for this * algorithm. */ public OBJECT_IDENTIFIER toOID() throws NoSuchAlgorithmException { if (oid == null) { throw new NoSuchAlgorithmException(); } else { return oid; } } /** * The type of parameter that this algorithm expects. Returns * null if this algorithm does not take any parameters. * If the algorithm can accept more than one type of parameter, * this method returns only one of them. It is better to call * getParameterClasses(). * * @return Parameter type. * @deprecated Call getParameterClasses() instead. */ @Deprecated public Class getParameterClass() { if (parameterClasses.length == 0) { return null; } else { return parameterClasses[0]; } } /** * The types of parameter that this algorithm expects. Returns * null if this algorithm does not take any parameters. * * @return Parameter types. */ public Class[] getParameterClasses() { return parameterClasses.clone(); } /** * Validates if the given Object can be used as a parameter * for this algorithm. *

* If null is passed in, this method will return true * if this algorithm takes no parameters, and false * if this algorithm does take parameters. * * @param o Object. * @return Returns true if the given Object can be used as a parameter. */ public boolean isValidParameterObject(Object o) { if (o == null) { return (parameterClasses.length == 0); } if (parameterClasses.length == 0) { return false; } Class c = o.getClass(); for (int i = 0; i < parameterClasses.length; ++i) { if (c.equals(parameterClasses[i])) { return true; } } return false; } public PKCS11Algorithm getEnum() { return PKCS11Algorithm.valueOfIndex(this.oidIndex); } /** * Index into the SECOidTag array in Algorithm.c. */ protected int oidIndex; String name; protected OBJECT_IDENTIFIER oid; private Class[] parameterClasses = new Class[0]; ////////////////////////////////////////////////////////////// // Algorithm OIDs ////////////////////////////////////////////////////////////// static final OBJECT_IDENTIFIER ANSI_X9_ALGORITHM = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 10040, 4 }); static final OBJECT_IDENTIFIER ANSI_X962_OID = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 10045 }); // Algorithm indices. These must be kept in sync with the // algorithm array in Algorithm.c. Any PKCS11 Algorithms must be added // to the org.mozilla.jss.crypto.PKCS11Algorithm enum. protected static final int SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION = 0; protected static final int SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION = 1; protected static final int SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION = 2; protected static final int SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST = 3; protected static final int SEC_OID_PKCS1_RSA_ENCRYPTION = 4; protected static final int CKM_RSA_PKCS_KEY_PAIR_GEN = 5; protected static final int CKM_DSA_KEY_PAIR_GEN = 6; protected static final int SEC_OID_ANSIX9_DSA_SIGNATURE = 7; protected static final int SEC_OID_RC4 = 8; protected static final int SEC_OID_DES_ECB = 9; protected static final int SEC_OID_DES_CBC = 10; protected static final int CKM_DES_CBC_PAD = 11; protected static final int CKM_DES3_ECB = 12; protected static final int SEC_OID_DES_EDE3_CBC = 13; protected static final int CKM_DES3_CBC_PAD = 14; protected static final int CKM_DES_KEY_GEN = 15; protected static final int CKM_DES3_KEY_GEN = 16; protected static final int CKM_RC4_KEY_GEN = 17; protected static final int SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC = 18; protected static final int SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC = 19; protected static final int SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC = 20; protected static final int SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4 = 21; protected static final int SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4 = 22; protected static final int SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC = 23; protected static final int SEC_OID_MD2 = 24; protected static final int SEC_OID_MD5 = 25; protected static final int SEC_OID_SHA1 = 26; protected static final int CKM_SHA_1_HMAC = 27; protected static final int SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC = 28; protected static final int SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC = 29; protected static final int SEC_OID_RC2_CBC = 30; protected static final int CKM_PBA_SHA1_WITH_SHA1_HMAC = 31; // AES protected static final int CKM_AES_KEY_GEN = 32; protected static final int CKM_AES_ECB = 33; protected static final int CKM_AES_CBC = 34; protected static final int CKM_AES_CBC_PAD = 35; protected static final int CKM_RC2_CBC_PAD = 36; protected static final int CKM_RC2_KEY_GEN = 37; //FIPS 180-2 protected static final int SEC_OID_SHA256 = 38; protected static final int SEC_OID_SHA384 = 39; protected static final int SEC_OID_SHA512 = 40; protected static final int SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION = 41; protected static final int SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION = 42; protected static final int SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION = 43; protected static final int SEC_OID_ANSIX962_EC_PUBLIC_KEY = 44; protected static final int SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE = 45; protected static final int CKM_EC_KEY_PAIR_GEN = 46; protected static final int SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE = 47; protected static final int SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE = 48; protected static final int SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE = 49; protected static final int SEC_OID_HMAC_SHA256 = 50; protected static final int SEC_OID_HMAC_SHA384 = 51; protected static final int SEC_OID_HMAC_SHA512 = 52; //PKCS5 V2 protected static final int SEC_OID_PKCS5_PBKDF2 = 53; protected static final int SEC_OID_PKCS5_PBES2 = 54; protected static final int SEC_OID_PKCS5_PBMAC1 = 55; protected static final int SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST = 56; // NSS AES KeyWrap protected static final int CKM_NSS_AES_KEY_WRAP = 57; protected static final int CKM_NSS_AES_KEY_WRAP_PAD = 58; // AES Encryption Algorithms protected static final int SEC_OID_AES_128_ECB = 59; protected static final int SEC_OID_AES_128_CBC = 60; protected static final int SEC_OID_AES_192_ECB = 61; protected static final int SEC_OID_AES_192_CBC = 62; protected static final int SEC_OID_AES_256_ECB = 63; protected static final int SEC_OID_AES_256_CBC = 64; // PKCS#11 AES KeyWrap // These underlying defs are currently different from the NSS AES KeyWrap protected static final int CKM_AES_KEY_WRAP = 65; protected static final int CKM_AES_KEY_WRAP_PAD = 66; // PKCS#11 SHA2 HMAC protected static final int CKM_SHA256_HMAC = 67; protected static final int CKM_SHA384_HMAC = 68; protected static final int CKM_SHA512_HMAC = 69; // PKCS#11 AES-CMAC protected static final int CKM_AES_CMAC = 70; // Generic Secret protected static final int CKM_GENERIC_SECRET_KEY_GEN = 71; // PKCS#11 NIST SP800-108 KBKDFs (including NSS variants) protected static final int CKM_SP800_108_COUNTER_KDF = 72; protected static final int CKM_SP800_108_FEEDBACK_KDF = 73; protected static final int CKM_SP800_108_DOUBLE_PIPELINE_KDF = 74; protected static final int CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA = 75; protected static final int CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA = 76; protected static final int CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA = 77; // RSA-PSS protected static final int SEC_OID_PKCS1_RSA_PSS_SIGNATURE = 78; // RSA-OAEP protected static final int CKM_RSA_PKCS_OAEP = 79; // CKM_AES_KEY_WRAP_KWP for HSM support protected static final int CKM_AES_KEY_WRAP_KWP = 80; protected static final int SEC_OID_AES_128_KEY_WRAP_KWP = 81; protected static final int SEC_OID_AES_192_KEY_WRAP_KWP = 82; protected static final int SEC_OID_AES_256_KEY_WRAP_KWP = 83; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/AlreadyInitializedException.java000066400000000000000000000016311412550063600276200ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; /** * This exception is thrown if an initialization operation * is attempted on something that is already initialized. */ public class AlreadyInitializedException extends java.lang.Exception { private static final long serialVersionUID = 1L; public AlreadyInitializedException() {} public AlreadyInitializedException(String mesg) { super(mesg); } public AlreadyInitializedException(String mesg, Throwable cause) { super(mesg, cause); } public AlreadyInitializedException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(mesg, cause, enableSuppression, writableStackTrace); } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/BadPaddingException.java000066400000000000000000000010761412550063600260310ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; /** * @deprecated Use javax.crypto.BadPaddingException. */ @Deprecated public class BadPaddingException extends javax.crypto.BadPaddingException { private static final long serialVersionUID = 1L; public BadPaddingException() { super(); } public BadPaddingException(String mesg) { super(mesg); } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/CMACAlgorithm.java000066400000000000000000000046711412550063600245530ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.NoSuchAlgorithmException; import java.util.Hashtable; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; /** * Algorithms for performing CMACs. These can be used to create * MessageDigests. */ public class CMACAlgorithm extends DigestAlgorithm { protected CMACAlgorithm(int oidIndex, String name, OBJECT_IDENTIFIER oid, int outputSize) { super(oidIndex, name, oid, outputSize); if (oid != null && oidMap.get(oid) == null) { oidMap.put(oid, this); } } /////////////////////////////////////////////////////////////////////// // OID mapping /////////////////////////////////////////////////////////////////////// private static Hashtable oidMap = new Hashtable<>(); /** * Looks up the CMAC algorithm with the given OID. * * @param oid OID. * @return CMAC algorithm. * @exception NoSuchAlgorithmException If no registered CMAC algorithm * has the given OID. */ public static CMACAlgorithm fromOID(OBJECT_IDENTIFIER oid) throws NoSuchAlgorithmException { CMACAlgorithm alg = oidMap.get(oid); if (alg == null) { throw new NoSuchAlgorithmException("No such algorithm for OID: " + oid); } return alg; } /** * CMAC AES-X. This is a Message Authentication Code that uses a * symmetric key together with the AES cipher to create a form of * signature. * * Note that we pass null for the OID here: neither NIST nor any other * standards body has defined an OID for use with CMAC. Since we use * a PKCS#11 backend and NSS doesn't otherwise define CMAC based on a * SEC OID, we don't strictly need one. * * We've left the fromOID code (and oid parameter in the constructor) as * other projects use them for HMACAlgorith. At such time as an OID is * defined, it can be added here. */ public static final CMACAlgorithm AES = new CMACAlgorithm(CKM_AES_CMAC, "AES-CMAC", null, 16); public static final CMACAlgorithm AES128 = AES; public static final CMACAlgorithm AES192 = AES; public static final CMACAlgorithm AES256 = AES; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/Cipher.java000066400000000000000000000167511412550063600234150ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.BadPaddingException; /** * A context for performing symmetric encryption and decryption. * First, the context must be initialized. Then, it can be updated * with input through zero or more calls to update. Finally, * doFinal is called to finalize the operation. Note that * it is not necessary to call update if all of the data is * available at once. In this case, all of the input can be processed with one * call to doFinal. */ public abstract class Cipher { // Note: Cipher can't extend javax.crypto.Cipher because it is part of the // provider mechanism. In particular, it isn't an abstract class, many of // the methods are marked final, and it expects to instantiate a CipherSpi // class instead of be directly created like things which override our // Cipher class expect (e.g., PK11Cipher). This is why JSSCipherSpi exists. /** * Initializes a encryption context with a symmetric key. */ public abstract void initEncrypt(SymmetricKey key) throws InvalidKeyException, InvalidAlgorithmParameterException, TokenException; /** * Initializes a decryption context with a symmetric key. */ public abstract void initDecrypt(SymmetricKey key) throws InvalidKeyException, InvalidAlgorithmParameterException, TokenException; /** * Initializes an encryption context with a symmetric key and * algorithm parameters. */ public abstract void initEncrypt(SymmetricKey key, AlgorithmParameterSpec parameters) throws InvalidKeyException, InvalidAlgorithmParameterException, TokenException; /** * Initializes a decryption context with a symmetric key and * algorithm parameters. */ public abstract void initDecrypt(SymmetricKey key, AlgorithmParameterSpec parameters) throws InvalidKeyException, InvalidAlgorithmParameterException, TokenException; /** * Updates the encryption context with additional input. * @param bytes Bytes of plaintext (if encrypting) or ciphertext (if * decrypting). * @return Bytes of ciphertext (if encrypting) or plaintext (if decrypting). */ public abstract byte[] update(byte[] bytes) throws IllegalStateException, TokenException; /** * Updates the encryption context with additional plaintext. * @param bytes Bytes of plaintext (if encrypting) or ciphertext (if * decrypting). * @param offset The index in bytes at which to begin reading. * @param length The number of bytes from bytes to read. * @return Bytes of ciphertext (if encrypting) or plaintext (if decrypting). */ public abstract byte[] update(byte[] bytes, int offset, int length) throws IllegalStateException, TokenException; /** * Completes an cipher operation. This can be called directly after * the context is initialized, or update may be called * any number of times before calling final. * @param bytes Bytes of plaintext (if encrypting) or ciphertext (if * decrypting). * @return The last of the output. */ public abstract byte[] doFinal(byte[] bytes) throws IllegalStateException, IllegalBlockSizeException, BadPaddingException, TokenException; /** * Completes an cipher operation. * @param bytes Bytes of plaintext (if encrypting) or ciphertext (if * decrypting). * @param offset The index in bytes at which to begin reading. * @param length The number of bytes from bytes to read. * @return The last of the output. */ public abstract byte[] doFinal(byte[] bytes, int offset, int length) throws IllegalStateException, IllegalBlockSizeException, BadPaddingException, TokenException; /** * Completes an cipher operation. * @return The last of the output. */ public abstract byte[] doFinal() throws IllegalStateException, IllegalBlockSizeException, BadPaddingException, TokenException; /** * Pads a byte array so that its length is a multiple of the given * blocksize. The method of padding is the one defined in the RSA * PKCS standards. If M is the length of the data and * B is the block size, the padding string consists of * B - (M mod B) octets, each having the value * B - (M mod B). * @param toBePadded The byte array to pad. * @param blockSize The block size of the encryption algorithm. Must be greater * than zero. * @see #unPad */ public static byte[] pad(byte[] toBePadded, int blockSize) { assert(blockSize > 0); // the padOctet is also the number of pad octets byte padOctet = (byte) (blockSize - (toBePadded.length % blockSize)); byte[] padded = new byte[toBePadded.length + padOctet]; System.arraycopy(toBePadded, 0, padded, 0, toBePadded.length); for(int i = toBePadded.length; i < padded.length; i++) { padded[i] = padOctet; } return padded; } /** * Un-pads a byte array that is padded with PKCS padding. * * @param blockSize The block size of the encryption algorithm. This * is only used for error checking: if the pad size is not * between 1 and blockSize, a BadPaddingException is thrown. * * @see #pad */ public static byte[] unPad(byte[] padded, int blockSize) throws BadPaddingException { if(padded.length == 0) { return new byte[0]; } if( padded.length < blockSize ) { throw new BadPaddingException("Length of padded array is less than"+ " one block"); } byte padOctet = padded[padded.length-1]; if(padOctet > blockSize) { throw new BadPaddingException("Padding octet ("+padOctet+") is "+ "larger than block size ("+blockSize+")"); } if(padOctet < 1) { throw new BadPaddingException("Padding octet is less than 1"); } byte[] unpadded = new byte[padded.length - padOctet]; System.arraycopy(padded, 0, unpadded, 0, unpadded.length); return unpadded; } /** * Un-pads a byte array that is padded with PKCS padding. Since * this version does not take block size as a parameter, it cannot * error check. * @see #pad */ public static byte[] unPad(byte[] padded) throws BadPaddingException { if(padded.length == 0) { return new byte[0]; } byte padOctet = padded[padded.length-1]; if(padOctet < 1) { throw new BadPaddingException("Padding octet is less than 1"); } else if(padOctet >= padded.length) { throw new BadPaddingException("Padding is larger than entire"+ " array"); } byte[] unpadded = new byte[padded.length - padOctet]; System.arraycopy(padded, 0, unpadded, 0, unpadded.length); return unpadded; } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/CryptoStore.java000066400000000000000000000157201412550063600244730ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.PublicKey; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.util.Password; /** * This is an interface for a permanent repository of cryptographic objects, * such as keys, certs, and passwords. */ public interface CryptoStore { //////////////////////////////////////////////////////////// // Private Keys //////////////////////////////////////////////////////////// /** * Imports a raw private key into this token (permanently). * * @param key The private key. * @exception TokenException If the key cannot be imported to this token. * @exception KeyAlreadyImportedException If the key already exists on this token. */ public PrivateKey importPrivateKey( byte[] key, PrivateKey.Type type ) throws TokenException, KeyAlreadyImportedException; /** * Imports a raw private key into this token. * * @param key The private key. * @param temporary Whether the key should be temporary. * @exception TokenException If the key cannot be imported to this token. * @exception KeyAlreadyImportedException If the key already exists on this token. */ public PrivateKey importPrivateKey( byte[] key, PrivateKey.Type type, boolean temporary) throws TokenException, KeyAlreadyImportedException; /** * Returns all private keys stored on this token. * * @return An array of all private keys stored on this token. * @exception TokenException If an error occurs on the token while * gathering the keys. */ public PrivateKey[] getPrivateKeys() throws TokenException; /** * Returns all public keys stored on this token. * * @return An array of all public keys stored on this token. * @exception TokenException If an error occurs on the token while * gathering the keys. */ public PublicKey[] getPublicKeys() throws TokenException; /** * Returns the public key corresponding to the private key. * * @param privateKey * @return The corresponding public key. * @throws ObjectNotFoundException If the corresponding public key is not found. * @throws TokenException If an error occurs on the token. */ public PublicKey findPublicKey(PrivateKey privateKey) throws ObjectNotFoundException, TokenException; /** * Returns all symmetric keys stored on this token. * * @return An array of all symmetric keys stored on this token. * @exception TokenException If an error occurs on the token while * gathering the keys. */ public SymmetricKey[] getSymmetricKeys() throws TokenException; /** * Permanently deletes a private key from the token. * * @param privateKey A private key to be permanently deleted. * @exception NoSuchItemOnTokenException If the given private key does * not reside on this token. * @exception TokenException If an error occurs on the token while * deleting the key. */ public void deletePrivateKey(PrivateKey privateKey) throws NoSuchItemOnTokenException, TokenException; /** * Permanently deletes a public key from the token. * * @param publicKey A public key to be permanently deleted. * @exception NoSuchItemOnTokenException If the given public key does * not reside on this token. * @exception TokenException If an error occurs on the token while * deleting the key. */ public void deletePublicKey(PublicKey publicKey) throws NoSuchItemOnTokenException, TokenException; /** * Get an encrypted private key for the given cert. * * @param cert Certificate of key to be exported * @param pbeAlg The PBEAlgorithm to use * @param pw The password to encrypt with * @param iteration Iteration count; default of 2000 if le 0 */ public byte[] getEncryptedPrivateKeyInfo(X509Certificate cert, PBEAlgorithm pbeAlg, Password pw, int iteration) throws NotInitializedException, ObjectNotFoundException, TokenException; /** * Get an encrypted private key, with optional password * conversion. * * @param conv Password converter. If null, pw.getByteCopy() * will be used to get password bytes. * @param pw The password * @param alg The encryption algorithm * @param n Iteration count; default of 2000 if le 0 * @param k The private key */ public byte[] getEncryptedPrivateKeyInfo( KeyGenerator.CharToByteConverter conv, Password pw, Algorithm alg, int n, PrivateKey k); /** * @param conv Password converter. If null, pw.getByteCopy() * will be used to get password bytes. * @param pw The password * @param nickname Nickname to use for private key * @param pubKey Public key corresponding to private key */ public void importEncryptedPrivateKeyInfo( KeyGenerator.CharToByteConverter conv, Password pw, String nickname, PublicKey pubKey, byte[] epkiBytes); //////////////////////////////////////////////////////////// // Certs //////////////////////////////////////////////////////////// /** * Returns all user certificates stored on this token. A user certificate * is one that has a matching private key. * * @return An array of all user certificates present on this token. * @exception TokenException If an error occurs on the token while * gathering the certificates. */ public X509Certificate[] getCertificates() throws TokenException; /** * Deletes a certificate and the corresponding keys. * * @param cert A certificate to be deleted from this token. The cert * must actually reside on this token. * @exception NoSuchItemOnTokenException If the given cert does not * reside on this token. * @exception TokenException If an error occurred on the token while * deleting the certificate. */ public void deleteCert(X509Certificate cert) throws NoSuchItemOnTokenException, TokenException; /** * Deletes a certificate without deleting the corresponding keys. * * @param cert A certificate to be deleted from this token. The cert * must actually reside on this token. * @exception NoSuchItemOnTokenException If the given cert does not * reside on this token. * @exception TokenException If an error occurred on the token while * deleting the certificate. */ public void deleteCertOnly(X509Certificate cert) throws NoSuchItemOnTokenException, TokenException; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/CryptoToken.java000066400000000000000000000270161412550063600244600ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.DigestException; import java.security.InvalidKeyException; import java.security.InvalidParameterException; import java.security.PublicKey; import org.mozilla.jss.util.IncorrectPasswordException; import org.mozilla.jss.util.PasswordCallback; /** * A CryptoToken performs cryptographic operations and stores * cryptographic items, such as keys and certs. It corresponds to a * Cryptographic Service Provider (CSP) in CDSA, and to a PKCS #11 token. *

* Instances of CryptoToken are obtained from CryptoManager. * * @see org.mozilla.jss.CryptoManager */ public interface CryptoToken { // // SERVICES // /** * Creates a Signature object, which can perform signing and signature * verification. Signing and verification cryptographic operations will * take place on this token. The signing key must be located on this * token. * * @param algorithm The algorithm used for the signing/verification. * @exception java.security.NoSuchAlgorithmException If the given * algorithm is not supported by this provider. */ public abstract org.mozilla.jss.crypto.Signature getSignatureContext(SignatureAlgorithm algorithm) throws java.security.NoSuchAlgorithmException, TokenException; /** * Creates a Digest object. Digesting cryptographic operations will * take place on this token. * * @param algorithm The algorithm used for digesting. * @exception java.security.NoSuchAlgorithmException If this provider * does not support the given algorithm. */ public abstract JSSMessageDigest getDigestContext(DigestAlgorithm algorithm) throws java.security.NoSuchAlgorithmException, DigestException; // !!! MAC ??? /** * Creates a Cipher object, which can be used for encryption and * decryption. Cryptographic operations will take place on this token. * The keys used in the operations must be located on this token. * * @param algorithm The algorithm used for encryption/decryption. * @exception java.security.NoSuchAlgorithmException If this provider * does not support the given algorithm. */ public abstract Cipher getCipherContext(EncryptionAlgorithm algorithm) throws java.security.NoSuchAlgorithmException, TokenException; public abstract SymmetricKeyDeriver getSymmetricKeyDeriver() throws TokenException; public abstract KeyWrapper getKeyWrapper(KeyWrapAlgorithm algorithm) throws java.security.NoSuchAlgorithmException, TokenException; /** * Returns a Random Number Generator implemented on this token. * * @exception org.mozilla.jss.crypto.ServiceNotProvidedException If this token * does not perform random number generation */ /* public abstract SecureRandom getRandomGenerator() throws NotImplementedException, TokenException; */ // !!! Derive Keys ??? /** * Creates a KeyGenerator object, which can be used to generate * symmetric encryption keys. Any keys generated with this KeyGenerator * will be generated on this token. * * @param algorithm The algorithm that the keys will be used with. * @exception java.security.NoSuchAlgorithmException If this token does not * support the given algorithm. */ public abstract KeyGenerator getKeyGenerator(KeyGenAlgorithm algorithm) throws java.security.NoSuchAlgorithmException, TokenException; /** * Clones a SymmetricKey from a different token onto this token. * * @exception SymmetricKey.NotExtractableException If the key material * cannot be extracted from the current token. * @exception InvalidKeyException If the owning token cannot process * the key to be cloned. */ public SymmetricKey cloneKey(SymmetricKey key) throws SymmetricKey.NotExtractableException, InvalidKeyException, TokenException; /** * Creates a KeyPairGenerator object, which can be used to generate * key pairs. Any keypairs generated with this generator will be generated * on this token. * * @param algorithm The algorithm that the keys will be used with (RSA, * DSA, EC, etc.) * @exception java.security.NoSuchAlgorithmException If this token does * not support the given algorithm. */ public abstract KeyPairGenerator getKeyPairGenerator(KeyPairAlgorithm algorithm) throws java.security.NoSuchAlgorithmException, TokenException; /** * Generates a b64 encoded PKCS10 blob used for making cert * request. Begin/End brackets included. * * @param subject subject dn of the certificate * @param keysize size of the key * @param keyType "rsa" or "dsa" * @param P The DSA prime parameter * @param Q The DSA sub-prime parameter * @param G The DSA base parameter * @return base64 encoded pkcs10 certificate request with * Begin/end brackets */ public abstract String generateCertRequest(String subject, int keysize, String keyType, byte[] P, byte[] Q, byte[] G) throws TokenException, InvalidParameterException, PQGParamGenException; /** * Determines whether this token supports the given algorithm. * * @param alg A JSS algorithm. Note that for Signature, a token may * fail to support a specific SignatureAlgorithm (such as * RSASignatureWithMD5Digest) even though it does support the * generic algorithm (RSASignature). In this case, the signature * operation will be performed on that token, but the digest * operation will be performed on the internal token. * @return true if the token supports the algorithm. */ public boolean doesAlgorithm(Algorithm alg); /** * Login to the token. If a token is logged in, it will not trigger * password callbacks. * * @param pwcb The password callback for this token. * @exception IncorrectPasswordException If the supplied password is * incorrect. * @see #setLoginMode * @see org.mozilla.jss.CryptoManager#setPasswordCallback */ public abstract void login(PasswordCallback pwcb) throws IncorrectPasswordException, TokenException; /** * Logout of the token. * */ public abstract void logout() throws TokenException; /** * Login once, never need to re-enter the password until you log out. */ public static final int ONE_TIME = 0; /** * Need to re-login after a period of time. * * @see org.mozilla.jss.crypto.CryptoToken#setLoginTimeoutMinutes */ public static final int TIMEOUT = 1; /** * Need to provide a password before each crypto operation. */ public static final int EVERY_TIME = 2; /** * Returns the login mode of this token: ONE_TIME, TIMEOUT, or * EVERY_TIME. The default is ONE_TIME. * * @see #getLoginTimeoutMinutes * @exception TokenException If an error occurs on the token. */ public abstract int getLoginMode() throws TokenException; /** * Sets the login mode of this token. * * @param mode ONE_TIME, TIMEOUT, or EVERY_TIME * @exception TokenException If this mode is not supported by this token, * or an error occurs on the token. * @see #login * @see #setLoginTimeoutMinutes */ public abstract void setLoginMode(int mode) throws TokenException; /** * Returns the login timeout period. The timeout is only used if the * login mode is TIMEOUT. * * @see #getLoginMode * @exception TokenException If an error occurs on the token. */ public abstract int getLoginTimeoutMinutes() throws TokenException; /** * Sets the timeout period for logging in. This will only be used * if the login mode is TIMEOUT. * * @exception TokenException If timeouts are not supported by this * token, or an error occurs on the token. * @see #setLoginMode */ public abstract void setLoginTimeoutMinutes(int timeoutMinutes) throws TokenException; /** * Find out if the token is currently logged in. * * @see #login * @see #logout */ public boolean isLoggedIn() throws TokenException; /** * returns true if this token needs to be logged into before * it can be used. * * @see #login * @see #logout */ public boolean needsLogin() throws TokenException; /** * Initialize the password of this token. * * @param securityOfficerPW A callback to obtain the password of the * SecurityOfficer. Pass in a NullPasswordCallback if there is * no security officer password. Must not be null. * @param userPW A callback to obtain the new password for this token. * Must not be null. * @exception IncorrectPasswordException If the supplied security officer * password is incorrect. * @exception AlreadyInitializedException If the token only allows one * password initialization, and it has already occurred. * @exception TokenException If an error occurs on the token. */ public abstract void initPassword(PasswordCallback securityOfficerPW, PasswordCallback userPW) throws IncorrectPasswordException, AlreadyInitializedException, TokenException; /** * Determine whether the password has been initialized yet. Some tokens * (such as the Netscape Internal Key Token) don't allow initializing * the PIN more than once. * * @exception TokenException If an error occurs on the token. */ public abstract boolean passwordIsInitialized() throws TokenException; /** * Change the password of this token. * * @exception IncorrectPasswordException If the supplied old password is * incorrect. * @param oldpw A callback (which could be just a Password) to retrieve * the current password. * @param newpw A callback (which could be just a Password) to retrieve * the new password. */ public abstract void changePassword(PasswordCallback oldpw, PasswordCallback newpw) throws IncorrectPasswordException, TokenException; /** * Obtain the nickname, or label, of this token. * * @exception TokenException If an error occurs on the token. */ public abstract String getName() throws TokenException; /** * Get the CryptoStore interface to this token's objects. */ public abstract CryptoStore getCryptoStore(); /** * Deep comparison operation. Use this, rather than ==, to determine * whether two CryptoTokens are the same. */ @Override public boolean equals(Object object); /** * Determines whether this token is currently present. * This could return false if the token is a smart card that was * removed from its slot. */ public boolean isPresent(); public void importPublicKey( PublicKey pubKey, boolean permanent) throws TokenException; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/DigestAlgorithm.java000066400000000000000000000055611412550063600252660ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.NoSuchAlgorithmException; import java.util.Hashtable; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; public class DigestAlgorithm extends Algorithm { // The size in bytes of the output of this hash. private int outputSize; protected DigestAlgorithm(int oidIndex, String name, OBJECT_IDENTIFIER oid, int outputSize) { super(oidIndex, name, oid); this.outputSize = outputSize; // only store the first algorithm for a given oid. More than one // alg might share the same oid, such as from child classes. if( oid != null && oidMap.get(oid)==null ) { oidMap.put(oid, this); } } /////////////////////////////////////////////////////////////////////// // OID mapping /////////////////////////////////////////////////////////////////////// private static Hashtable oidMap = new Hashtable<>(); public static DigestAlgorithm fromOID(OBJECT_IDENTIFIER oid) throws NoSuchAlgorithmException { DigestAlgorithm alg = oidMap.get(oid); if( alg == null ) { throw new NoSuchAlgorithmException(); } else { return alg; } } /** * @return The output size in bytes for this algorithm. */ public int getOutputSize() { return outputSize; } /** * The MD2 digest algorithm, from RSA. */ public static final DigestAlgorithm MD2 = new DigestAlgorithm (SEC_OID_MD2, "MD2", OBJECT_IDENTIFIER.RSA_DIGEST.subBranch(2), 16 ); /** * The MD5 digest algorithm, from RSA. */ public static final DigestAlgorithm MD5 = new DigestAlgorithm (SEC_OID_MD5, "MD5", OBJECT_IDENTIFIER.RSA_DIGEST.subBranch(5), 16 ); /** * The SHA-1 digest algorithm, from Uncle Sam. */ public static final DigestAlgorithm SHA1 = new DigestAlgorithm (SEC_OID_SHA1, "SHA-1", OBJECT_IDENTIFIER.ALGORITHM.subBranch(26), 20); /* * The SHA-256 digest Algorithm from FIPS 180-2 */ public static final DigestAlgorithm SHA256 = new DigestAlgorithm (SEC_OID_SHA256, "SHA-256", OBJECT_IDENTIFIER.HASH_ALGORITHM.subBranch(1), 32); /* * The SHA-384 digest Algorithm from FIPS 180-2 */ public static final DigestAlgorithm SHA384 = new DigestAlgorithm (SEC_OID_SHA384, "SHA-384", OBJECT_IDENTIFIER.HASH_ALGORITHM.subBranch(2), 48); /* * The SHA-512 digest Algorithm from FIPS 180-2 */ public static final DigestAlgorithm SHA512 = new DigestAlgorithm (SEC_OID_SHA512, "SHA-512", OBJECT_IDENTIFIER.HASH_ALGORITHM.subBranch(3), 64); } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/EncryptionAlgorithm.java000066400000000000000000000373001412550063600261750ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.NoSuchAlgorithmException; import java.util.Hashtable; import java.util.Vector; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.RC2ParameterSpec; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; /** * An algorithm for performing symmetric encryption. */ public class EncryptionAlgorithm extends Algorithm { public static class Mode { private String name; private static Hashtable nameHash = new Hashtable<>(); private Mode() { } private Mode(String name) { this.name = name; nameHash.put(name.toLowerCase(), this); } public static Mode fromString(String name) throws NoSuchAlgorithmException { Mode m = nameHash.get(name.toLowerCase()); if (m == null) { throw new NoSuchAlgorithmException( "Unrecognized mode \"" + name + "\""); } return m; } @Override public String toString() { return name; } public static final Mode NONE = new Mode("NONE"); public static final Mode ECB = new Mode("ECB"); public static final Mode CBC = new Mode("CBC"); } public static class Alg { private String name; private static Hashtable nameHash = new Hashtable<>(); private Alg() { } private Alg(String name) { this.name = name; nameHash.put(name.toLowerCase(), this); } private static Alg fromString(String name) throws NoSuchAlgorithmException { Alg a = nameHash.get(name.toLowerCase()); if (a == null) { throw new NoSuchAlgorithmException("Unrecognized algorithm \"" + name + "\""); } return a; } @Override public String toString() { return name; } public static final Alg RC4 = new Alg("RC4"); public static final Alg DES = new Alg("DES"); public static final Alg DESede = new Alg("DESede"); public static final Alg AES = new Alg("AES"); public static final Alg RC2 = new Alg("RC2"); } public static class Padding { private String name; private static Hashtable nameHash = new Hashtable<>(); private Padding() { } private Padding(String name) { this.name = name; nameHash.put(name.toLowerCase(), this); } @Override public String toString() { return name; } public static Padding fromString(String name) throws NoSuchAlgorithmException { Padding p = nameHash.get(name.toLowerCase()); if (p == null) { throw new NoSuchAlgorithmException("Unrecognized Padding " + "type \"" + name + "\""); } return p; } public static final Padding NONE = new Padding("NoPadding"); public static final Padding PKCS5 = new Padding("PKCS5Padding"); } private static String makeName(Alg alg, Mode mode, Padding padding) { StringBuffer buf = new StringBuffer(); buf.append(alg.toString()); buf.append('/'); buf.append(mode.toString()); buf.append('/'); buf.append(padding.toString()); return buf.toString(); } protected EncryptionAlgorithm(int oidTag, Alg alg, Mode mode, Padding padding, Class paramClass, int blockSize, OBJECT_IDENTIFIER oid, int keyStrength) { super(oidTag, makeName(alg, mode, padding), oid, paramClass); this.alg = alg; this.mode = mode; this.padding = padding; this.blockSize = blockSize; if (oid != null) { oidMap.put(oid, this); } if (name != null) { nameMap.put(name.toLowerCase(), this); } this.keyStrength = keyStrength; algList.addElement(this); } protected EncryptionAlgorithm(int oidTag, Alg alg, Mode mode, Padding padding, Class[] paramClasses, int blockSize, OBJECT_IDENTIFIER oid, int keyStrength) { super(oidTag, makeName(alg, mode, padding), oid, paramClasses); this.alg = alg; this.mode = mode; this.padding = padding; this.blockSize = blockSize; if (oid != null) { oidMap.put(oid, this); } if (name != null) { nameMap.put(name.toLowerCase(), this); } this.keyStrength = keyStrength; algList.addElement(this); } protected EncryptionAlgorithm(int oidTag, Alg alg, Mode mode, Padding padding, Class paramClass, int blockSize, OBJECT_IDENTIFIER oid, int keyStrength,String name) { super(oidTag, name, oid, paramClass); this.alg = alg; this.mode = mode; this.padding = padding; this.blockSize = blockSize; if(oid!=null) { oidMap.put(oid, this); } if( name != null ) { nameMap.put(name.toLowerCase(), this); } this.keyStrength = keyStrength; algList.addElement(this); } protected EncryptionAlgorithm(int oidTag, Alg alg, Mode mode, Padding padding, Class []paramClasses, int blockSize, OBJECT_IDENTIFIER oid, int keyStrength,String name) { super(oidTag, name, oid, paramClasses); this.alg = alg; this.mode = mode; this.padding = padding; this.blockSize = blockSize; if(oid!=null) { oidMap.put(oid, this); } if( name != null ) { nameMap.put(name.toLowerCase(), this); } this.keyStrength = keyStrength; algList.addElement(this); } private int blockSize; private Alg alg; private Mode mode; private Padding padding; private int keyStrength; /** * @return The base algorithm, without the parameters. For example, * the base algorithm of "AES/CBC/NoPadding" is "AES". */ public Alg getAlg() { return alg; } /** * @return The mode of this algorithm. */ public Mode getMode() { return mode; } /** * @return The padding type of this algorithm. */ public Padding getPadding() { return padding; } /** * @return The key strength of this algorithm in bits. Algorithms that * use continuously variable key sizes (such as RC4) will return 0 to * indicate they can use any key size. */ public int getKeyStrength() { return keyStrength; } /////////////////////////////////////////////////////////////////////// // mapping /////////////////////////////////////////////////////////////////////// private static Hashtable oidMap = new Hashtable<>(); private static Hashtable nameMap = new Hashtable<>(); private static Vector algList = new Vector<>(); public static EncryptionAlgorithm fromOID(OBJECT_IDENTIFIER oid) throws NoSuchAlgorithmException { Object alg = oidMap.get(oid); if (alg == null) { throw new NoSuchAlgorithmException("OID: " + oid.toString()); } else { return (EncryptionAlgorithm) alg; } } // Note: after we remove this deprecated method, we can remove // nameMap. /** * @param name Algorithm name. * @return Encryption algorithm. * @throws NoSuchAlgorithmException If the algorithm is not found. * @deprecated This method is deprecated because algorithm strings * don't contain key length, which is necessary to distinguish between * AES algorithms. */ @Deprecated public static EncryptionAlgorithm fromString(String name) throws NoSuchAlgorithmException { Object alg = nameMap.get(name.toLowerCase()); if (alg == null) { throw new NoSuchAlgorithmException(); } else { return (EncryptionAlgorithm) alg; } } public static EncryptionAlgorithm lookup(String algName, String modeName, String paddingName, int keyStrength) throws NoSuchAlgorithmException { int len = algList.size(); Alg alg = Alg.fromString(algName); Mode mode = Mode.fromString(modeName); Padding padding = Padding.fromString(paddingName); if (paddingName == null || paddingName.equals("")) padding = Padding.NONE; int i; for (i = 0; i < len; ++i) { EncryptionAlgorithm cur = algList.elementAt(i); if (cur.alg == alg && cur.mode == mode && cur.padding == padding) { if (cur.keyStrength == 0 || cur.keyStrength == keyStrength) { break; } } } if (i == len) { throw new NoSuchAlgorithmException(algName + "/" + modeName + "/" + paddingName + " with key strength " + keyStrength + " not found"); } return algList.elementAt(i); } /** * @return The blocksize of the algorithm in bytes. Stream algorithms (such as * RC4) have a blocksize of 1. */ public int getBlockSize() { return blockSize; } /** * @return true if this algorithm performs padding. */ public boolean isPadded() { return !Padding.NONE.equals(padding); } /** * @return The type of padding for this algorithm. */ public Padding getPaddingType() { return padding; } private static Class[] IVParameterSpecClasses = null; static { IVParameterSpecClasses = new Class[2]; IVParameterSpecClasses[0] = IVParameterSpec.class; IVParameterSpecClasses[1] = IvParameterSpec.class; } /** * Returns the number of bytes that this algorithm expects in * its initialization vector. * * @return The size in bytes of the IV for this algorithm. A size of * 0 means this algorithm does not take an IV. */ public native int getIVLength(); public static final EncryptionAlgorithm RC4 = new EncryptionAlgorithm(SEC_OID_RC4, Alg.RC4, Mode.NONE, Padding.NONE, (Class) null, 1, OBJECT_IDENTIFIER.RSA_CIPHER.subBranch(4), 0); public static final EncryptionAlgorithm DES_ECB = new EncryptionAlgorithm(SEC_OID_DES_ECB, Alg.DES, Mode.ECB, Padding.NONE, (Class) null, 8, OBJECT_IDENTIFIER.ALGORITHM.subBranch(6), 56); public static final EncryptionAlgorithm DES_CBC = new EncryptionAlgorithm(SEC_OID_DES_CBC, Alg.DES, Mode.CBC, Padding.NONE, IVParameterSpecClasses, 8, OBJECT_IDENTIFIER.ALGORITHM.subBranch(7), 56); public static final EncryptionAlgorithm DES_CBC_PAD = new EncryptionAlgorithm(CKM_DES_CBC_PAD, Alg.DES, Mode.CBC, Padding.PKCS5, IVParameterSpecClasses, 8, null, 56); // no oid public static final EncryptionAlgorithm DES3_ECB = new EncryptionAlgorithm(CKM_DES3_ECB, Alg.DESede, Mode.ECB, Padding.NONE, (Class) null, 8, null, 168); // no oid public static final EncryptionAlgorithm DES3_CBC = new EncryptionAlgorithm(SEC_OID_DES_EDE3_CBC, Alg.DESede, Mode.CBC, Padding.NONE, IVParameterSpecClasses, 8, OBJECT_IDENTIFIER.RSA_CIPHER.subBranch(7), 168); public static final EncryptionAlgorithm DES3_CBC_PAD = new EncryptionAlgorithm(CKM_DES3_CBC_PAD, Alg.DESede, Mode.CBC, Padding.PKCS5, IVParameterSpecClasses, 8, null, 168); //no oid public static final EncryptionAlgorithm RC2_CBC = new EncryptionAlgorithm(SEC_OID_RC2_CBC, Alg.RC2, Mode.CBC, Padding.NONE, RC2ParameterSpec.class, 8, null, 0); // no oid, see comment below // Which algorithm should be associated with this OID, RC2_CBC or // RC2_CBC_PAD? NSS says RC2_CBC, but PKCS #5 v2.0 says RC2_CBC_PAD. // See NSS bug 202925. public static final EncryptionAlgorithm RC2_CBC_PAD = new EncryptionAlgorithm(CKM_RC2_CBC_PAD, Alg.RC2, Mode.CBC, Padding.PKCS5, RC2ParameterSpec.class, 8, OBJECT_IDENTIFIER.RSA_CIPHER.subBranch(2), 0); public static final OBJECT_IDENTIFIER AES_ROOT_OID = new OBJECT_IDENTIFIER( new long[] { 2, 16, 840, 1, 101, 3, 4, 1 }); public static final EncryptionAlgorithm AES_128_ECB = new EncryptionAlgorithm(SEC_OID_AES_128_ECB, Alg.AES, Mode.ECB, Padding.NONE, (Class) null, 16, AES_ROOT_OID.subBranch(1), 128); public static final EncryptionAlgorithm AES_128_CBC = new EncryptionAlgorithm(SEC_OID_AES_128_CBC, Alg.AES, Mode.CBC, Padding.NONE, IVParameterSpecClasses, 16, AES_ROOT_OID.subBranch(2), 128); public static final EncryptionAlgorithm AES_128_CBC_PAD = new EncryptionAlgorithm(SEC_OID_AES_128_CBC, Alg.AES, Mode.CBC, Padding.PKCS5, IVParameterSpecClasses, 16, AES_ROOT_OID.subBranch(2), 128); public static final EncryptionAlgorithm AES_192_ECB = new EncryptionAlgorithm(SEC_OID_AES_192_ECB, Alg.AES, Mode.ECB, Padding.NONE, (Class) null, 16, AES_ROOT_OID.subBranch(21), 192); public static final EncryptionAlgorithm AES_192_CBC = new EncryptionAlgorithm(SEC_OID_AES_192_CBC, Alg.AES, Mode.CBC, Padding.NONE, IVParameterSpecClasses, 16, AES_ROOT_OID.subBranch(22), 192); public static final EncryptionAlgorithm AES_192_CBC_PAD = new EncryptionAlgorithm(SEC_OID_AES_192_CBC, Alg.AES, Mode.CBC, Padding.PKCS5, IVParameterSpecClasses, 16, AES_ROOT_OID.subBranch(22), 192); public static final EncryptionAlgorithm AES_256_ECB = new EncryptionAlgorithm(SEC_OID_AES_256_ECB, Alg.AES, Mode.ECB, Padding.NONE, (Class) null, 16, AES_ROOT_OID.subBranch(41), 256); public static final EncryptionAlgorithm AES_256_CBC = new EncryptionAlgorithm(SEC_OID_AES_256_CBC, Alg.AES, Mode.CBC, Padding.NONE, IVParameterSpecClasses, 16, AES_ROOT_OID.subBranch(42), 256); public static final EncryptionAlgorithm AES_CBC_PAD = new EncryptionAlgorithm(CKM_AES_CBC_PAD, Alg.AES, Mode.CBC, Padding.PKCS5, IVParameterSpecClasses, 16, null, 256); // no oid public static final EncryptionAlgorithm AES_256_CBC_PAD = new EncryptionAlgorithm(SEC_OID_AES_256_CBC, Alg.AES, Mode.CBC, Padding.PKCS5, IVParameterSpecClasses, 16, AES_ROOT_OID.subBranch(42), 256); public static final EncryptionAlgorithm AES_128_KEY_WRAP_KWP = new EncryptionAlgorithm(SEC_OID_AES_128_KEY_WRAP_KWP, Alg.AES,Mode.NONE, Padding.PKCS5, IVParameterSpecClasses, 16, AES_ROOT_OID.subBranch(8), 128,"AES/None/PKCS5Padding/Kwp/128"); public static final EncryptionAlgorithm AES_192_KEY_WRAP_KWP = new EncryptionAlgorithm(SEC_OID_AES_192_KEY_WRAP_KWP, Alg.AES,Mode.NONE, Padding.PKCS5, IVParameterSpecClasses, 16, AES_ROOT_OID.subBranch(28), 192,"AES/None/PKCSPadding/Kwp/192"); public static final EncryptionAlgorithm AES_256_KEY_WRAP_KWP = new EncryptionAlgorithm(SEC_OID_AES_256_KEY_WRAP_KWP, Alg.AES,Mode.NONE, Padding.PKCS5, IVParameterSpecClasses, 16, AES_ROOT_OID.subBranch(48), 256,"AES/None/PKCS5Padding/Kwp/256"); } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/HMACAlgorithm.java000066400000000000000000000045611412550063600245560ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.NoSuchAlgorithmException; import java.util.Hashtable; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; /** * Algorithms for performing HMACs. These can be used to create * MessageDigests. */ public class HMACAlgorithm extends DigestAlgorithm { protected HMACAlgorithm(int oidIndex, String name, OBJECT_IDENTIFIER oid, int outputSize) { super(oidIndex, name, oid, outputSize); if( oid!=null && oidMap.get(oid)==null) { oidMap.put(oid, this); } } /////////////////////////////////////////////////////////////////////// // OID mapping /////////////////////////////////////////////////////////////////////// private static Hashtable oidMap = new Hashtable<>(); /** * Looks up the HMAC algorithm with the given OID. * * @param oid OID. * @return HMAC algorithm. * @exception NoSuchAlgorithmException If no registered HMAC algorithm * has the given OID. */ public static HMACAlgorithm fromOID(OBJECT_IDENTIFIER oid) throws NoSuchAlgorithmException { Object alg = oidMap.get(oid); if( alg == null ) { throw new NoSuchAlgorithmException(); } else { return (HMACAlgorithm) alg; } } /** * SHA-X HMAC. This is a Message Authentication Code that uses a * symmetric key together with SHA-X digesting to create a form of * signature. */ public static final HMACAlgorithm SHA1 = new HMACAlgorithm (CKM_SHA_1_HMAC, "SHA-1-HMAC", OBJECT_IDENTIFIER.ALGORITHM.subBranch(26), 20); public static final HMACAlgorithm SHA256 = new HMACAlgorithm (CKM_SHA256_HMAC, "SHA-256-HMAC", OBJECT_IDENTIFIER.RSA_DIGEST.subBranch(9), 32); public static final HMACAlgorithm SHA384 = new HMACAlgorithm (CKM_SHA384_HMAC, "SHA-384-HMAC", OBJECT_IDENTIFIER.RSA_DIGEST.subBranch(10), 48); public static final HMACAlgorithm SHA512 = new HMACAlgorithm (CKM_SHA512_HMAC, "SHA-512-HMAC", OBJECT_IDENTIFIER.RSA_DIGEST.subBranch(11), 64); } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/IVParameterSpec.java000066400000000000000000000011121412550063600251560ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import javax.crypto.spec.IvParameterSpec; /** * An algorithm parameter that consists of an initialization vector (IV). */ public class IVParameterSpec extends IvParameterSpec { public IVParameterSpec(byte[] iv) { super(iv); } public IVParameterSpec(byte[] iv, int offset, int len) { super(iv, offset, len); } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/IllegalBlockSizeException.java000066400000000000000000000005401412550063600272260ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; public class IllegalBlockSizeException extends Exception { private static final long serialVersionUID = 1L; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/InternalCertificate.java000066400000000000000000000047241412550063600261170ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; /** * Certificates residing in the internal database. Their trust flags * can be viewed and modified. Other types of certificates do not * have trust flags. */ public interface InternalCertificate extends X509Certificate { //////////////////////////////////////////////////// // Trust manipulation //////////////////////////////////////////////////// public static final int VALID_PEER = (1<<0); public static final int TRUSTED_PEER = (1<<1); // CERTDB_TRUSTED public static final int VALID_CA = (1<<3); public static final int TRUSTED_CA = (1<<4); public static final int USER = (1<<6); public static final int TRUSTED_CLIENT_CA = (1<<7); /** * Set the SSL trust flags for this certificate. * * @param trust A bitwise OR of the trust flags VALID_PEER, VALID_CA, * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. */ public abstract void setSSLTrust(int trust); /** * Set the email (S/MIME) trust flags for this certificate. * * @param trust A bitwise OR of the trust flags VALID_PEER, VALID_CA, * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. */ public abstract void setEmailTrust(int trust); /** * Set the object signing trust flags for this certificate. * * @param trust A bitwise OR of the trust flags VALID_PEER, VALID_CA, * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. */ public abstract void setObjectSigningTrust(int trust); /** * Get the SSL trust flags for this certificate. * * @return A bitwise OR of the trust flags VALID_PEER, VALID_CA, * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. */ public abstract int getSSLTrust(); /** * Get the email (S/MIME) trust flags for this certificate. * * @return A bitwise OR of the trust flags VALID_PEER, VALID_CA, * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. */ public abstract int getEmailTrust(); /** * Get the object signing trust flags for this certificate. * * @return A bitwise OR of the trust flags VALID_PEER, VALID_CA, * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. */ public abstract int getObjectSigningTrust(); } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/InvalidDERException.java000066400000000000000000000014431412550063600257730ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; /** * This exception is thrown when we encounter a bogus DER blob. */ public class InvalidDERException extends Exception { private static final long serialVersionUID = 1L; public InvalidDERException() { super(); } public InvalidDERException(String mesg) { super(mesg); } public InvalidDERException(String mesg, Throwable cause) { super(mesg, cause); } public InvalidDERException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(mesg, cause, enableSuppression, writableStackTrace); } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/InvalidKeyFormatException.java000066400000000000000000000014661412550063600272670ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; /** * An exception of this type is thrown if an encoded private key * cannot be decoded. */ public class InvalidKeyFormatException extends java.security.spec.InvalidKeySpecException { private static final long serialVersionUID = 1L; public InvalidKeyFormatException() { super(); } public InvalidKeyFormatException(String mesg) { super(mesg); } public InvalidKeyFormatException(String mesg, Throwable cause) { super(mesg, cause); } public InvalidKeyFormatException(Throwable cause) { super(cause); } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/JSSMessageDigest.java000066400000000000000000000075101412550063600253000ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.DigestException; import java.security.InvalidKeyException; /** * A class for performing message digesting (hashing) and MAC operations. */ public abstract class JSSMessageDigest { /** * Initializes an HMAC digest with the given symmetric key. This also * has the effect of resetting the digest. * * @param key Symmetric key. * @exception DigestException If this algorithm is not an HMAC algorithm. * @exception InvalidKeyException If the given key is not valid. */ public abstract void initHMAC(SymmetricKey key) throws DigestException, InvalidKeyException; /** * Updates the digest with a single byte of input. * @param input Input byte. * @throws DigestException If an error occurred. */ public void update(byte input) throws DigestException { byte[] in = { input }; update(in, 0, 1); } /** * Updates the digest with a portion of an array. * * @param input An array from which to update the digest. * @param offset The index in the array at which to start digesting. * @param len The number of bytes to digest. * @exception DigestException If an error occurs while digesting. */ public abstract void update(byte[] input, int offset, int len) throws DigestException; /** * Updates the digest with an array. * * @param input An array to feed to the digest. * @exception DigestException If an error occurs while digesting. */ public void update(byte[] input) throws DigestException { update(input, 0, input.length); } /** * Completes digestion. * * @return The, ahem, output of the digest operation. * @exception DigestException If an error occurs while digesting. */ public byte[] digest() throws DigestException { byte[] output = new byte[getOutputSize()]; digest(output, 0, output.length); return output; } /** * Completes digesting, storing the result into the provided array. * * @param buf The buffer in which to place the digest output. * @param offset The offset in the buffer at which to store the output. * @param len The amount of space available in the buffer for the * digest output. * @return The number of bytes actually stored into buf. * @exception DigestException If the provided space is too small for * the digest, or an error occurs with the digest. */ public abstract int digest(byte[] buf, int offset, int len) throws DigestException; /** * Provides final data to the digest, then completes it and returns the * output. * * @param input The digest's last meal. * @return The completed digest. * @exception DigestException If an error occurs while digesting. */ public byte[] digest(byte[] input) throws DigestException { update(input); return digest(); } /** * Resets this digest for further use. This clears all input and * output streams. If this is an HMAC digest, the HMAC key is not * cleared. * @throws DigestException If an error occurred. */ public abstract void reset() throws DigestException; /** * @return The algorithm that this digest uses. */ public abstract DigestAlgorithm getAlgorithm(); /** * Returns the length of the digest created by this digest's * digest algorithm. * * @return The size in bytes of the output of this digest. */ public int getOutputSize() { return getAlgorithm().getOutputSize(); } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/JSSOAEPParameterSpec.c000066400000000000000000000077211412550063600252610ustar00rootroot00000000000000#include #include #include #include #include #include "_jni/org_mozilla_jss_crypto_JSSOAEPParameterSpec.h" #include "jssutil.h" #include "java_ids.h" #include "jss_exceptions.h" #include "pk11util.h" #include "NativeEnclosure.h" #include "StaticVoidPointer.h" PRStatus oaep_GetHashAlg(JNIEnv *env, jobject this, jclass this_class, CK_MECHANISM_TYPE *ret) { jfieldID field_id = NULL; field_id = (*env)->GetFieldID(env, this_class, "hashAlg", "J"); if (field_id == NULL) { return PR_FAILURE; } *ret = (*env)->GetLongField(env, this, field_id); return PR_SUCCESS; } PRStatus oaep_GetMGFType(JNIEnv *env, jobject this, jclass this_class, CK_RSA_PKCS_MGF_TYPE *ret) { jfieldID field_id = NULL; field_id = (*env)->GetFieldID(env, this_class, "mgf", "J"); if (field_id == NULL) { return PR_FAILURE; } *ret = (*env)->GetLongField(env, this, field_id); return PR_SUCCESS; } PRStatus oaep_GetSpecifiedSourceData(JNIEnv *env, jobject this, jclass this_class, CK_VOID_PTR *ret, CK_ULONG *ret_len) { jfieldID field_id = NULL; jbyteArray data = NULL; field_id = (*env)->GetFieldID(env, this_class, "sourceData", "[B"); if (field_id == NULL) { return PR_FAILURE; } data = (*env)->GetObjectField(env, this, field_id); if (data == NULL) { *ret = NULL; *ret_len = 0; return PR_SUCCESS; } if (!JSS_FromByteArray(env, data, (uint8_t **)ret, ret_len)) { return PR_FAILURE; } return PR_SUCCESS; } JNIEXPORT void JNICALL Java_org_mozilla_jss_crypto_JSSOAEPParameterSpec_acquireNativeResources(JNIEnv *env, jobject this) { jclass this_class = NULL; CK_MECHANISM_TYPE hashAlg; CK_RSA_PKCS_MGF_TYPE mgf; CK_RSA_PKCS_OAEP_SOURCE_TYPE source = CKZ_DATA_SPECIFIED; CK_VOID_PTR pSourceData = NULL; CK_ULONG ulSourceDataLen = 0; CK_RSA_PKCS_OAEP_PARAMS_PTR oaep_params = NULL; jobject params_obj; this_class = (*env)->GetObjectClass(env, this); if (this_class == NULL) { return; } if (oaep_GetHashAlg(env, this, this_class, &hashAlg) != PR_SUCCESS) { return; } if (oaep_GetMGFType(env, this, this_class, &mgf) != PR_SUCCESS) { return; } /* Here on down, we need to go to failure on error, to free our * allocated data. */ if (oaep_GetSpecifiedSourceData(env, this, this_class, &pSourceData, &ulSourceDataLen) != PR_SUCCESS) { goto failure; } oaep_params = calloc(1, sizeof(CK_RSA_PKCS_OAEP_PARAMS)); oaep_params->hashAlg = hashAlg; oaep_params->mgf = mgf; oaep_params->source = source; oaep_params->pSourceData = pSourceData; oaep_params->ulSourceDataLen = ulSourceDataLen; params_obj = JSS_PR_wrapStaticVoidPointer(env, (void **)&oaep_params); if (params_obj == NULL) { goto failure; } if (JSS_PR_StoreNativeEnclosure(env, this, params_obj, sizeof(CK_RSA_PKCS_OAEP_PARAMS)) != PR_SUCCESS) { goto failure; } return; failure: free(pSourceData); free(oaep_params); } JNIEXPORT void JNICALL Java_org_mozilla_jss_crypto_JSSOAEPParameterSpec_releaseNativeResources(JNIEnv *env, jobject this) { jobject ptr_object = NULL; CK_RSA_PKCS_OAEP_PARAMS_PTR oaep_params = NULL; jlong params_length; PR_ASSERT(env != NULL && this != NULL); if (JSS_PR_LoadNativeEnclosure(env, this, &ptr_object, ¶ms_length) != PR_SUCCESS) { return; } if (JSS_PR_getStaticVoidRef(env, ptr_object, (void **)&oaep_params) != PR_SUCCESS || oaep_params == NULL) { return; } PR_ASSERT(params_length == sizeof(CK_RSA_PKCS_OAEP_PARAMS)); if (oaep_params->ulSourceDataLen != 0 && oaep_params->pSourceData != NULL) { memset(oaep_params->pSourceData, 0, sizeof(CK_VOID_PTR) * oaep_params->ulSourceDataLen); free(oaep_params->pSourceData); } memset(oaep_params, 0, sizeof(CK_RSA_PKCS_OAEP_PARAMS)); free(oaep_params); } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/JSSOAEPParameterSpec.java000066400000000000000000000150101412550063600257460ustar00rootroot00000000000000package org.mozilla.jss.crypto; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.MGF1ParameterSpec; import javax.crypto.spec.OAEPParameterSpec; import javax.crypto.spec.PSource; import org.mozilla.jss.pkcs11.PKCS11Constants; import org.mozilla.jss.util.NativeEnclosure; /** * This class is utilized by JSS to implement OAEP support. * * Unlike the existing OAEPParameterSpec in the JCA, this class supports * NativeEnclosure, allowing it to be used within low-level JNI calls. We * support copying from an existing OAEPParameterSpec instance (so use is * interchangeable within JSS) and support setting members from JSS-specific * types. * * Note that this class cannot be used with other JCA providers natively. */ public class JSSOAEPParameterSpec extends NativeEnclosure implements AlgorithmParameterSpec { public long hashAlg; public long mgf; public byte[] sourceData; public JSSOAEPParameterSpec(String mdName, String mgfName, AlgorithmParameterSpec mgfSpec, PSource pSrc) { setDigestAlgorithm(mdName); setMaskGenAlgorithm(mgfName); setMaskGenAlgorithmType(mgfSpec); setPSource(pSrc); } public JSSOAEPParameterSpec(OAEPParameterSpec copy) { setDigestAlgorithm(copy.getDigestAlgorithm()); setMaskGenAlgorithm(copy.getMGFAlgorithm()); setMaskGenAlgorithmType(copy.getMGFParameters()); setPSource(copy.getPSource()); } public void setDigestAlgorithm(String algo) throws IllegalArgumentException { switch (algo.toLowerCase()) { case "md5": case "ckm_md5": hashAlg = PKCS11Constants.CKM_MD5; break; case "sha1": case "sha-1": case "ckm_sha_1": hashAlg = PKCS11Constants.CKM_SHA_1; break; case "sha256": case "sha-256": case "ckm_sha256": hashAlg = PKCS11Constants.CKM_SHA256; break; case "sha384": case "sha-384": case "ckm_sha384": hashAlg = PKCS11Constants.CKM_SHA384; break; case "sha512": case "sha-512": case "ckm_sha512": hashAlg = PKCS11Constants.CKM_SHA512; break; default: String msg = "Unknown algorithm identifier: " + algo; throw new IllegalArgumentException(msg); } } public void setDigestAlgorithm(DigestAlgorithm algo) throws IllegalArgumentException { if ((algo instanceof HMACAlgorithm) || (algo instanceof CMACAlgorithm)) { String msg = "Unable to use MAC digest algorithm " + algo; msg += " in place of an unkeyed hash algorithm"; throw new IllegalArgumentException(msg); } hashAlg = algo.getEnum().getValue(); } public void setDigestAlgorithm(long algo) throws IllegalArgumentException { hashAlg = algo; } public void setMaskGenAlgorithm(String algo) throws IllegalArgumentException { if (!algo.toLowerCase().equals("mgf1")) { String msg = "Unknown mask generation algorithm: " + algo; throw new IllegalArgumentException(msg); } // Do nothing. We just validate this data so if we get passed // something unexpected, we error out instead. } public void setMaskGenAlgorithmType(String algo) throws IllegalArgumentException { switch (algo.toLowerCase()) { case "sha1": case "sha-1": case "ckm_sha_1": hashAlg = PKCS11Constants.CKG_MGF1_SHA1; break; case "sha256": case "sha-256": case "ckm_sha256": hashAlg = PKCS11Constants.CKG_MGF1_SHA256; break; case "sha384": case "sha-384": case "ckm_sha384": hashAlg = PKCS11Constants.CKG_MGF1_SHA384; break; case "sha512": case "sha-512": case "ckm_sha512": hashAlg = PKCS11Constants.CKG_MGF1_SHA512; break; default: String msg = "Unknown mask generation algorithm identifier: " + algo; throw new IllegalArgumentException(msg); } } public void setMaskGenAlgorithmType(AlgorithmParameterSpec algo) throws IllegalArgumentException { if (!(algo instanceof MGF1ParameterSpec) || algo == null) { String msg = "Unknown mask generation algorithm parameter "; msg += "specification: " + algo; throw new IllegalArgumentException(msg); } MGF1ParameterSpec mgf1 = (MGF1ParameterSpec) algo; switch (mgf1.getDigestAlgorithm().toLowerCase()) { case "sha1": case "sha-1": mgf = PKCS11Constants.CKG_MGF1_SHA1; break; case "sha256": case "sha-256": mgf = PKCS11Constants.CKG_MGF1_SHA256; break; case "sha384": case "sha-384": mgf = PKCS11Constants.CKG_MGF1_SHA384; break; case "sha512": case "sha-512": mgf = PKCS11Constants.CKG_MGF1_SHA512; break; default: String msg = "Unknown mask generation algorithm identifier: "; msg += mgf1.getDigestAlgorithm(); throw new IllegalArgumentException(msg); } } public void setMaskGenAlgorithmType(long algo) throws IllegalArgumentException { mgf = algo; } public void setPSource(PSource spec) throws IllegalArgumentException { if (spec == null) { sourceData = null; return; } if (!(spec instanceof PSource.PSpecified)) { String msg = "Expected PSource spec to be an instance of "; msg += "PSource.PSpecified, but wasn't: " + spec; throw new IllegalArgumentException(msg); } PSource.PSpecified value = (PSource.PSpecified) spec; setPSource(value.getValue()); } public void setPSource(byte[] data) throws IllegalArgumentException { // PSource.PSpecified.DEFAULT is an allocated byte array of 0 length. // This confuses JSS_FromByteArray(...) into thinking that an error // occurred. Because PKCS#11 accepts a NULL pointer to go with a 0 // length array, just set sourceData to NULL. if (data == null || data.length == 0) { sourceData = null; return; } sourceData = data; } @Override protected native void acquireNativeResources() throws Exception; @Override protected native void releaseNativeResources() throws Exception; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/JSSSecureRandom.java000066400000000000000000000014121412550063600251360ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; /** * An interface for secure random numbers. */ public interface JSSSecureRandom { /** * Seed the RNG with the given seed bytes. * @param seed Seed. */ public void setSeed(byte[] seed); /** * Seed the RNG with the eight bytes contained in seed. * @param seed Seed. */ public void setSeed(long seed); /** * Retrieves random bytes and stores them in the given array. * @param bytes Array to store random bytes. */ public void nextBytes(byte bytes[]); } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/KBKDF.c000066400000000000000000000733041412550063600223220ustar00rootroot00000000000000#include #include #include #include #include #include "_jni/org_mozilla_jss_crypto_KBKDFByteArrayParam.h" #include "_jni/org_mozilla_jss_crypto_KBKDFCounterParams.h" #include "_jni/org_mozilla_jss_crypto_KBKDFDerivedKey.h" #include "_jni/org_mozilla_jss_crypto_KBKDFDKMLengthParam.h" #include "_jni/org_mozilla_jss_crypto_KBKDFFeedbackParams.h" #include "_jni/org_mozilla_jss_crypto_KBKDFIterationVariableParam.h" #include "_jni/org_mozilla_jss_crypto_KBKDFOptionalCounterParam.h" #include "_jni/org_mozilla_jss_crypto_KBKDFPipelineParams.h" #include "jssutil.h" #include "java_ids.h" #include "jss_exceptions.h" #include "pk11util.h" #include "CKAttribute.h" #include "NativeEnclosure.h" #include "StaticVoidPointer.h" #ifndef CKM_SP800_108_COUNTER_KDF #define __NOT_IMPLEMENTED__(name) JNIEXPORT void JNICALL \ name(JNIEnv *env, jobject this) \ { \ JSS_throwMsg(env, UNSUPPORTED_OPERATION_EXCEPTION, \ "KBKDF Operations aren't supported by the version of NSS that JSS was compiled against."); \ } __NOT_IMPLEMENTED__(Java_org_mozilla_jss_crypto_KBKDFByteArrayParam_acquireNativeResourcesInternal); __NOT_IMPLEMENTED__(Java_org_mozilla_jss_crypto_KBKDFByteArrayParam_releaseNativeResourcesInternal); __NOT_IMPLEMENTED__(Java_org_mozilla_jss_crypto_KBKDFCounterParams_acquireNativeResourcesInternal); __NOT_IMPLEMENTED__(Java_org_mozilla_jss_crypto_KBKDFCounterParams_releaseNativeResourcesInternal); __NOT_IMPLEMENTED__(Java_org_mozilla_jss_crypto_KBKDFDerivedKey_acquireNativeResourcesInternal); __NOT_IMPLEMENTED__(Java_org_mozilla_jss_crypto_KBKDFDerivedKey_releaseNativeResourcesInternal); __NOT_IMPLEMENTED__(Java_org_mozilla_jss_crypto_KBKDFDKMLengthParam_acquireNativeResources); __NOT_IMPLEMENTED__(Java_org_mozilla_jss_crypto_KBKDFDKMLengthParam_releaseNativeResources); __NOT_IMPLEMENTED__(Java_org_mozilla_jss_crypto_KBKDFFeedbackParams_acquireNativeResourcesInternal); __NOT_IMPLEMENTED__(Java_org_mozilla_jss_crypto_KBKDFFeedbackParams_releaseNativeResourcesInternal); __NOT_IMPLEMENTED__(Java_org_mozilla_jss_crypto_KBKDFIterationVariableParam_acquireNativeResources); __NOT_IMPLEMENTED__(Java_org_mozilla_jss_crypto_KBKDFIterationVariableParam_releaseNativeResources); __NOT_IMPLEMENTED__(Java_org_mozilla_jss_crypto_KBKDFOptionalCounterParam_acquireNativeResources); __NOT_IMPLEMENTED__(Java_org_mozilla_jss_crypto_KBKDFOptionalCounterParam_releaseNativeResources); __NOT_IMPLEMENTED__(Java_org_mozilla_jss_crypto_KBKDFPipelineParams_acquireNativeResourcesInternal); __NOT_IMPLEMENTED__(Java_org_mozilla_jss_crypto_KBKDFPipelineParams_releaseNativeResourcesInternal); JNIEXPORT jobject JNICALL Java_org_mozilla_jss_crypto_KBKDFDerivedKey_getKeyFromHandle(JNIEnv *env, jobject this, jobject parentKey, jlong mech, jboolean temporary) { JSS_throwMsg(env, UNSUPPORTED_OPERATION_EXCEPTION, "KBKDF Operations aren't supported by the version of NSS that JSS was compiled against."); return NULL; } #else /* ===== KBKDF Data Parameter Wrappers ===== */ PRStatus kbkdf_WrapDataParam(JNIEnv *env, jobject this, jclass *this_class, void *ptr, size_t ptr_length) { jfieldID field_id = NULL; size_t param_length = sizeof(CK_PRF_DATA_PARAM); CK_PRF_DATA_PARAM_PTR param = calloc(1, param_length); jobject ptr_object = NULL; PR_ASSERT(env != NULL && this != NULL && this_class != NULL && param != NULL); if (*this_class == NULL) { *this_class = (*env)->GetObjectClass(env, this); if (*this_class == NULL) { goto failure; } } field_id = (*env)->GetFieldID(env, *this_class, "type", "J"); if (field_id == NULL) { goto failure; } param->type = (CK_PRF_DATA_TYPE)((*env)->GetLongField(env, this, field_id)); param->pValue = ptr; param->ulValueLen = ptr_length; ptr_object = JSS_PR_wrapStaticVoidPointer(env, (void **)¶m); if (ptr_object == NULL) { goto failure; } if (JSS_PR_StoreNativeEnclosure(env, this, ptr_object, param_length) != PR_SUCCESS) { goto failure; } return PR_SUCCESS; failure: memset(param, 0, param_length); free(param); return PR_FAILURE; } PRStatus kbkdf_UnwrapDataParam(JNIEnv *env, jobject this, CK_PRF_DATA_PARAM_PTR *param, size_t *param_length) { jobject ptr_object = NULL; jlong size = 0; PR_ASSERT(env != NULL && this != NULL && param != NULL && param_length != NULL); if (JSS_PR_LoadNativeEnclosure(env, this, &ptr_object, &size) != PR_SUCCESS) { goto failure; } if (JSS_PR_getStaticVoidRef(env, ptr_object, (void **)param) != PR_SUCCESS || *param == NULL) { goto failure; } *param_length = size; return PR_SUCCESS; failure: *param = NULL; *param_length = 0; return PR_FAILURE; } /* ===== KBKDF Byte Array Parameter ===== */ JNIEXPORT void JNICALL Java_org_mozilla_jss_crypto_KBKDFByteArrayParam_acquireNativeResourcesInternal(JNIEnv *env, jobject this) { jclass this_class = NULL; jfieldID field_id; jbyteArray this_data; uint8_t *array = NULL; size_t length = 0; PR_ASSERT(env != NULL && this != NULL); this_class = (*env)->GetObjectClass(env, this); if (this_class == NULL) { return; } field_id = (*env)->GetFieldID(env, this_class, "data", "[B"); if (field_id == NULL) { return; } this_data = (*env)->GetObjectField(env, this, field_id); if (this_data == NULL) { return; } if (!JSS_FromByteArray(env, this_data, &array, &length)) { return; } /* From here on out, we need to zero and free our copy of the array before * returning from error cases. */ if (kbkdf_WrapDataParam(env, this, &this_class, array, length) != PR_SUCCESS) { goto failure; } return; failure: memset(array, 0, length); free(array); } JNIEXPORT void JNICALL Java_org_mozilla_jss_crypto_KBKDFByteArrayParam_releaseNativeResourcesInternal(JNIEnv *env, jobject this) { CK_PRF_DATA_PARAM_PTR param; size_t param_size = 0; if (kbkdf_UnwrapDataParam(env, this, ¶m, ¶m_size) != PR_SUCCESS) { return; } PR_ASSERT(param_size = sizeof(CK_PRF_DATA_PARAM)); PR_ASSERT(param->type == CK_SP800_108_BYTE_ARRAY); if (param->pValue != NULL) { memset(param->pValue, 0, param->ulValueLen); } free(param->pValue); if (param != NULL) { memset(param, 0, param_size); } free(param); } /* ===== KBKDF Interation Variable Parameter ===== */ JNIEXPORT void JNICALL Java_org_mozilla_jss_crypto_KBKDFIterationVariableParam_acquireNativeResources(JNIEnv *env, jobject this) { jclass this_class = NULL; jfieldID field_id; jboolean littleEndian = JNI_FALSE; jlong widthInBits = 0; CK_SP800_108_COUNTER_FORMAT_PTR data = NULL; size_t data_length = 0; this_class = (*env)->GetObjectClass(env, this); if (this_class == NULL) { return; } field_id = (*env)->GetFieldID(env, this_class, "littleEndian", "Z"); if (field_id == NULL) { return; } littleEndian = (*env)->GetBooleanField(env, this, field_id); field_id = (*env)->GetFieldID(env, this_class, "widthInBits", "J"); if (field_id == NULL) { return; } widthInBits = (*env)->GetLongField(env, this, field_id); if (widthInBits == 0) { return; } if (widthInBits >= 8) { data_length = sizeof(CK_SP800_108_COUNTER_FORMAT); data = calloc(1, data_length); if (data == NULL) { return; } /* From here on out we need to goto failure, freeing data on failure. */ data->bLittleEndian = (littleEndian == JNI_TRUE) ? CK_TRUE : CK_FALSE; data->ulWidthInBits = (CK_ULONG)widthInBits; } if (kbkdf_WrapDataParam(env, this, &this_class, data, data_length) != PR_SUCCESS) { goto failure; } return; failure: memset(data, 0, sizeof(CK_SP800_108_COUNTER_FORMAT)); free(data); } JNIEXPORT void JNICALL Java_org_mozilla_jss_crypto_KBKDFIterationVariableParam_releaseNativeResources(JNIEnv *env, jobject this) { CK_PRF_DATA_PARAM_PTR param; size_t param_size = 0; if (kbkdf_UnwrapDataParam(env, this, ¶m, ¶m_size) != PR_SUCCESS) { return; } PR_ASSERT(param_size = sizeof(CK_PRF_DATA_PARAM)); PR_ASSERT(param->type == CK_SP800_108_ITERATION_VARIABLE); if (param->pValue != NULL) { PR_ASSERT(param->ulValueLen == sizeof(CK_SP800_108_COUNTER_FORMAT)); memset(param->pValue, 0, param->ulValueLen); free(param->pValue); } if (param != NULL) { memset(param, 0, param_size); free(param); } } /* ===== KBKDF Optional Counter Parameter ===== */ JNIEXPORT void JNICALL Java_org_mozilla_jss_crypto_KBKDFOptionalCounterParam_acquireNativeResources(JNIEnv *env, jobject this) { jclass this_class = NULL; jfieldID field_id; jboolean littleEndian = JNI_FALSE; jlong widthInBits = 0; CK_SP800_108_COUNTER_FORMAT_PTR data = NULL; size_t data_length = 0; this_class = (*env)->GetObjectClass(env, this); if (this_class == NULL) { return; } field_id = (*env)->GetFieldID(env, this_class, "littleEndian", "Z"); if (field_id == NULL) { return; } littleEndian = (*env)->GetBooleanField(env, this, field_id); field_id = (*env)->GetFieldID(env, this_class, "widthInBits", "J"); if (field_id == NULL) { return; } widthInBits = (*env)->GetLongField(env, this, field_id); if (widthInBits == 0) { return; } data_length = sizeof(CK_SP800_108_COUNTER_FORMAT); data = calloc(1, data_length); if (data == NULL) { return; } /* From here on out we need to goto failure, freeing data on failure. */ data->bLittleEndian = (littleEndian == JNI_TRUE) ? CK_TRUE : CK_FALSE; data->ulWidthInBits = (CK_ULONG)widthInBits; if (kbkdf_WrapDataParam(env, this, &this_class, data, data_length) != PR_SUCCESS) { goto failure; } return; failure: memset(data, 0, sizeof(CK_SP800_108_COUNTER_FORMAT)); free(data); } JNIEXPORT void JNICALL Java_org_mozilla_jss_crypto_KBKDFOptionalCounterParam_releaseNativeResources(JNIEnv *env, jobject this) { CK_PRF_DATA_PARAM_PTR param; size_t param_size = 0; if (kbkdf_UnwrapDataParam(env, this, ¶m, ¶m_size) != PR_SUCCESS) { return; } PR_ASSERT(param_size = sizeof(CK_PRF_DATA_PARAM)); PR_ASSERT(param->type == CK_SP800_108_OPTIONAL_COUNTER); PR_ASSERT(param->ulValueLen == sizeof(CK_SP800_108_COUNTER_FORMAT)); if (param->pValue != NULL) { memset(param->pValue, 0, param->ulValueLen); free(param->pValue); } if (param != NULL) { memset(param, 0, param_size); free(param); } } /* ===== KBKDF DKM Length Parameter ===== */ JNIEXPORT void JNICALL Java_org_mozilla_jss_crypto_KBKDFDKMLengthParam_acquireNativeResources(JNIEnv *env, jobject this) { jclass this_class = NULL; jfieldID field_id; jlong method = 0; jboolean littleEndian = JNI_FALSE; jlong widthInBits = 0; CK_SP800_108_DKM_LENGTH_FORMAT_PTR data = NULL; size_t data_length = 0; this_class = (*env)->GetObjectClass(env, this); if (this_class == NULL) { return; } field_id = (*env)->GetFieldID(env, this_class, "lengthMethod", "J"); if (field_id == NULL) { return; } method = (*env)->GetLongField(env, this, field_id); field_id = (*env)->GetFieldID(env, this_class, "littleEndian", "Z"); if (field_id == NULL) { return; } littleEndian = (*env)->GetBooleanField(env, this, field_id); field_id = (*env)->GetFieldID(env, this_class, "widthInBits", "J"); if (field_id == NULL) { return; } widthInBits = (*env)->GetLongField(env, this, field_id); if (widthInBits == 0) { return; } data_length = sizeof(CK_SP800_108_DKM_LENGTH_FORMAT); data = calloc(1, data_length); if (data == NULL) { return; } /* From here on out we need to goto failure, freeing data on failure. */ data->dkmLengthMethod = (CK_SP800_108_DKM_LENGTH_METHOD)method; data->bLittleEndian = (littleEndian == JNI_TRUE) ? CK_TRUE : CK_FALSE; data->ulWidthInBits = (CK_ULONG)widthInBits; if (kbkdf_WrapDataParam(env, this, &this_class, data, data_length) != PR_SUCCESS) { goto failure; } return; failure: memset(data, 0, sizeof(CK_SP800_108_DKM_LENGTH_FORMAT)); free(data); } JNIEXPORT void JNICALL Java_org_mozilla_jss_crypto_KBKDFDKMLengthParam_releaseNativeResources(JNIEnv *env, jobject this) { CK_PRF_DATA_PARAM_PTR param; size_t param_size = 0; if (kbkdf_UnwrapDataParam(env, this, ¶m, ¶m_size) != PR_SUCCESS) { return; } PR_ASSERT(param_size = sizeof(CK_PRF_DATA_PARAM)); PR_ASSERT(param->type == CK_SP800_108_DKM_LENGTH); PR_ASSERT(param->ulValueLen == sizeof(CK_SP800_108_DKM_LENGTH_FORMAT)); if (param->pValue != NULL) { memset(param->pValue, 0, param->ulValueLen); free(param->pValue); } if (param != NULL) { memset(param, 0, param_size); free(param); } } /* ===== KBKDF Derived Keys ===== */ JNIEXPORT void JNICALL Java_org_mozilla_jss_crypto_KBKDFDerivedKey_acquireNativeResourcesInternal(JNIEnv *env, jobject this) { jclass this_class = NULL; jfieldID field_id = NULL; CK_ATTRIBUTE_PTR attrs = NULL; CK_ULONG num_attrs = 0; CK_OBJECT_HANDLE_PTR key_handle = NULL; CK_DERIVED_KEY_PTR ptr = NULL; jobject ptr_obj = NULL; jobjectArray attrs_array = NULL; this_class = (*env)->GetObjectClass(env, this); if (this_class == NULL) { goto failure; } field_id = (*env)->GetFieldID(env, this_class, "attrs", "[L" CK_ATTRIBUTE_CLASS_NAME ";"); if (field_id == NULL) { goto failure; } attrs_array = (*env)->GetObjectField(env, this, field_id); if (attrs_array == NULL) { goto failure; } num_attrs = (*env)->GetArrayLength(env, attrs_array); attrs = calloc(num_attrs, sizeof(CK_ATTRIBUTE)); for (size_t offset = 0; offset < num_attrs; offset++) { jobject this_attr_obj; CK_ATTRIBUTE_PTR attr; this_attr_obj = (*env)->GetObjectArrayElement(env, attrs_array, offset); if (this_attr_obj == NULL) { goto failure; } if (JSS_PK11_UnwrapAttribute(env, this_attr_obj, &attr) != PR_SUCCESS) { goto failure; } attrs[offset] = *attr; } key_handle = calloc(1, sizeof(CK_OBJECT_HANDLE)); if (key_handle == NULL) { goto failure; } ptr = calloc(1, sizeof(CK_DERIVED_KEY)); if (ptr == NULL) { goto failure; } ptr->pTemplate = attrs; ptr->ulAttributeCount = num_attrs; ptr->phKey = key_handle; ptr_obj = JSS_PR_wrapStaticVoidPointer(env, (void **)&ptr); if (ptr_obj == NULL) { goto failure; } if (JSS_PR_StoreNativeEnclosure(env, this, ptr_obj, sizeof(CK_DERIVED_KEY)) != PR_SUCCESS) { goto failure; } return; failure: if (attrs != NULL) { memset(attrs, 0, num_attrs * sizeof(CK_ATTRIBUTE)); free(attrs); } if (key_handle != NULL) { memset(key_handle, 0, sizeof(CK_OBJECT_HANDLE)); free(key_handle); } if (ptr != NULL) { memset(ptr, 0, sizeof(CK_DERIVED_KEY)); free(ptr); } } JNIEXPORT void JNICALL Java_org_mozilla_jss_crypto_KBKDFDerivedKey_releaseNativeResourcesInternal(JNIEnv *env, jobject this) { jclass this_class = NULL; jfieldID field_id = NULL; jobject ptr_obj = NULL; jlong size = 0; CK_DERIVED_KEY_PTR ptr = NULL; if (JSS_PR_LoadNativeEnclosure(env, this, &ptr_obj, &size) != PR_SUCCESS) { return; } if (JSS_PR_getStaticVoidRef(env, ptr_obj, (void **)&ptr) != PR_SUCCESS || ptr == NULL) { return; } PR_ASSERT(size == sizeof(CK_DERIVED_KEY)); /* Save off the derived key, if/when possible, before freeing the * underlying CK_DERIVED_KEY struct. */ if (ptr->phKey == NULL) { goto free; } this_class = (*env)->GetObjectClass(env, this); if (this_class == NULL) { goto free; } field_id = (*env)->GetFieldID(env, this_class, "handle", "J"); if (field_id == NULL) { goto free; } (*env)->SetLongField(env, this, field_id, *(ptr->phKey)); free: if (ptr->pTemplate != NULL) { memset(ptr->pTemplate, 0, ptr->ulAttributeCount * sizeof(CK_ATTRIBUTE)); free(ptr->pTemplate); } if (ptr->phKey != NULL) { memset(ptr->phKey, 0, sizeof(CK_OBJECT_HANDLE)); free(ptr->phKey); } memset(ptr, 0, sizeof(CK_DERIVED_KEY)); free(ptr); } JNIEXPORT jobject JNICALL Java_org_mozilla_jss_crypto_KBKDFDerivedKey_getKeyFromHandle(JNIEnv *env, jobject this, jobject parentKey, jlong mech, jboolean temporary) { jclass this_class = NULL; jfieldID field_id = NULL; CK_OBJECT_HANDLE handle = 0; PK11SymKey *parent = NULL; PK11SlotInfo *slot = NULL; PK11SymKey *key = NULL; PRBool is_perm = (temporary == JNI_TRUE) ? PR_FALSE : PR_TRUE; this_class = (*env)->GetObjectClass(env, this); if (this_class == NULL) { return NULL; } field_id = (*env)->GetFieldID(env, this_class, "handle", "J"); if (field_id == NULL) { return NULL; } handle = (CK_OBJECT_HANDLE)((*env)->GetLongField(env, this, field_id)); if (JSS_PK11_getSymKeyPtr(env, parentKey, &parent) != PR_SUCCESS || parent == NULL) { return NULL; } slot = PK11_GetSlotFromKey(parent); key = PK11_SymKeyFromHandle(slot, parent, PK11_OriginDerive, mech, handle, is_perm, NULL); PK11_FreeSlot(slot); return JSS_PK11_wrapSymKey(env, &key); } /* ===== KBKDF Parameter Helpers ===== */ PRStatus kbkdf_GetPRFType(JNIEnv *env, jobject this, jclass this_class, CK_SP800_108_PRF_TYPE *prf_type) { jfieldID field_id = NULL; field_id = (*env)->GetFieldID(env, this_class, "prf", "J"); if (field_id == NULL) { return PR_FAILURE; } *prf_type = (*env)->GetLongField(env, this, field_id); return PR_SUCCESS; } PRStatus kbkdf_GetDataParameters(JNIEnv *env, jobject this, jclass this_class, CK_ULONG *num_data_params, CK_PRF_DATA_PARAM_PTR *data_params) { jfieldID field_id = NULL; jobjectArray params_array = NULL; field_id = (*env)->GetFieldID(env, this_class, "params", "[L" KBKDF_DATA_PARAMETER_CLASS_NAME ";"); if (field_id == NULL) { return PR_FAILURE; } params_array = (*env)->GetObjectField(env, this, field_id); if (params_array == NULL) { return PR_FAILURE; } *num_data_params = (*env)->GetArrayLength(env, params_array); *data_params = calloc(*num_data_params, sizeof(CK_PRF_DATA_PARAM)); for (size_t offset = 0; offset < *num_data_params; offset++) { jobject this_param_object = NULL; CK_PRF_DATA_PARAM_PTR this_param = NULL; size_t this_param_size = 0; this_param_object = (*env)->GetObjectArrayElement(env, params_array, offset); if (this_param_object == NULL) { return PR_FAILURE; } if (kbkdf_UnwrapDataParam(env, this_param_object, &this_param, &this_param_size) != PR_SUCCESS) { return PR_FAILURE; } PR_ASSERT(this_param_size == sizeof(CK_PRF_DATA_PARAM)); (*data_params)[offset] = *this_param; } return PR_SUCCESS; } PRStatus kbkdf_GetAdditionalDerivedKeys(JNIEnv *env, jobject this, jclass this_class, CK_ULONG *num_additional_keys, CK_DERIVED_KEY_PTR *additional_keys) { jfieldID field_id = NULL; jobjectArray keys_array = NULL; field_id = (*env)->GetFieldID(env, this_class, "additional_keys", "[L" KBKDF_DERIVED_KEY_CLASS_NAME ";"); if (field_id == NULL) { return PR_FAILURE; } keys_array = (*env)->GetObjectField(env, this, field_id); if (keys_array == NULL) { *num_additional_keys = 0; *additional_keys = NULL; return PR_SUCCESS; } *num_additional_keys = (*env)->GetArrayLength(env, keys_array); *additional_keys = calloc(*num_additional_keys, sizeof(CK_DERIVED_KEY)); for (size_t offset = 0; offset < *num_additional_keys; offset++) { jobject this_key_object = NULL; CK_DERIVED_KEY_PTR this_key = NULL; jobject this_key_ptr = NULL; jlong this_key_size = 0; this_key_object = (*env)->GetObjectArrayElement(env, keys_array, offset); if (this_key_object == NULL) { return PR_FAILURE; } if (JSS_PR_LoadNativeEnclosure(env, this_key_object, &this_key_ptr, &this_key_size) != PR_SUCCESS) { return PR_FAILURE; } if (JSS_PR_getStaticVoidRef(env, this_key_ptr, (void **)&this_key) != PR_SUCCESS || this_key == NULL) { return PR_FAILURE; } PR_ASSERT(this_key_size == sizeof(CK_DERIVED_KEY)); (*additional_keys)[offset] = *this_key; } return PR_SUCCESS; } PRStatus kbkdf_GetInitialValue(JNIEnv *env, jobject this, jclass this_class, CK_ULONG *initial_value_length, CK_BYTE_PTR *initial_value) { jfieldID field_id = NULL; jobjectArray iv_array = NULL; field_id = (*env)->GetFieldID(env, this_class, "initial_value", "[B"); if (field_id == NULL) { return PR_FAILURE; } iv_array = (*env)->GetObjectField(env, this, field_id); if (iv_array == NULL) { *initial_value_length = 0; *initial_value = NULL; return PR_SUCCESS; } if (!JSS_FromByteArray(env, iv_array, initial_value, initial_value_length)) { return PR_FAILURE; } return PR_SUCCESS; } /* ===== KBKDF Counter Parameters ===== */ JNIEXPORT void JNICALL Java_org_mozilla_jss_crypto_KBKDFCounterParams_acquireNativeResourcesInternal(JNIEnv *env, jobject this) { jclass this_class = NULL; CK_SP800_108_PRF_TYPE prf_type = CKM_INVALID_MECHANISM; CK_ULONG num_data_params = 0; CK_PRF_DATA_PARAM_PTR data_params = NULL; CK_ULONG num_additional_keys = 0; CK_DERIVED_KEY_PTR additional_keys = NULL; CK_SP800_108_KDF_PARAMS_PTR kdf_params = NULL; jobject params_obj; this_class = (*env)->GetObjectClass(env, this); if (this_class == NULL) { return; } /* Handle PRF Type. */ if (kbkdf_GetPRFType(env, this, this_class, &prf_type) != PR_SUCCESS) { goto failure; } /* Handle Data Parameters. */ if (kbkdf_GetDataParameters(env, this, this_class, &num_data_params, &data_params) != PR_SUCCESS) { goto failure; } /* Handle Additional Derived Keys. */ if (kbkdf_GetAdditionalDerivedKeys(env, this, this_class, &num_additional_keys, &additional_keys) != PR_SUCCESS) { goto failure; } /* Place the values in the actual KDF params struct. */ kdf_params = calloc(1, sizeof(CK_SP800_108_KDF_PARAMS)); kdf_params->prfType = prf_type; kdf_params->ulNumberOfDataParams = num_data_params; kdf_params->pDataParams = data_params; kdf_params->ulAdditionalDerivedKeys = num_additional_keys; kdf_params->pAdditionalDerivedKeys = additional_keys; /* Place it back into this NativeEnclosure. */ params_obj = JSS_PR_wrapStaticVoidPointer(env, (void **)&kdf_params); if (params_obj == NULL) { goto failure; } if (JSS_PR_StoreNativeEnclosure(env, this, params_obj, sizeof(CK_SP800_108_KDF_PARAMS)) != PR_SUCCESS) { goto failure; } return; failure: if (data_params != NULL) { memset(data_params, 0, sizeof(CK_PRF_DATA_PARAM) * num_data_params); free(data_params); } if (additional_keys != NULL) { memset(additional_keys, 0, sizeof(CK_DERIVED_KEY) * num_additional_keys); free(additional_keys); } if (kdf_params != NULL) { memset(kdf_params, 0, sizeof(CK_SP800_108_KDF_PARAMS)); free(kdf_params); } } JNIEXPORT void JNICALL Java_org_mozilla_jss_crypto_KBKDFCounterParams_releaseNativeResourcesInternal(JNIEnv *env, jobject this) { jobject ptr_object = NULL; CK_SP800_108_KDF_PARAMS_PTR kdf_params = NULL; jlong params_length; PR_ASSERT(env != NULL && this != NULL); if (JSS_PR_LoadNativeEnclosure(env, this, &ptr_object, ¶ms_length) != PR_SUCCESS) { return; } if (JSS_PR_getStaticVoidRef(env, ptr_object, (void **)&kdf_params) != PR_SUCCESS || kdf_params == NULL) { return; } PR_ASSERT(params_length == sizeof(CK_SP800_108_KDF_PARAMS)); if (kdf_params->ulNumberOfDataParams != 0 && kdf_params->pDataParams != NULL) { memset(kdf_params->pDataParams, 0, sizeof(CK_PRF_DATA_PARAM) * kdf_params->ulNumberOfDataParams); free(kdf_params->pDataParams); } if (kdf_params->ulAdditionalDerivedKeys != 0 && kdf_params->pAdditionalDerivedKeys != NULL) { memset(kdf_params->pAdditionalDerivedKeys, 0, sizeof(CK_DERIVED_KEY) * kdf_params->ulAdditionalDerivedKeys); free(kdf_params->pAdditionalDerivedKeys); } memset(kdf_params, 0, params_length); free(kdf_params); } /* ===== KBKDF Feedback Parameters ===== */ JNIEXPORT void JNICALL Java_org_mozilla_jss_crypto_KBKDFFeedbackParams_acquireNativeResourcesInternal(JNIEnv *env, jobject this) { jclass this_class = NULL; CK_SP800_108_PRF_TYPE prf_type = CKM_INVALID_MECHANISM; CK_ULONG num_data_params = 0; CK_PRF_DATA_PARAM_PTR data_params = NULL; CK_ULONG num_additional_keys = 0; CK_DERIVED_KEY_PTR additional_keys = NULL; CK_ULONG initial_value_length = 0; CK_BYTE_PTR initial_value = NULL; CK_SP800_108_FEEDBACK_KDF_PARAMS_PTR kdf_params = NULL; jobject params_obj; this_class = (*env)->GetObjectClass(env, this); if (this_class == NULL) { return; } /* Handle PRF Type. */ if (kbkdf_GetPRFType(env, this, this_class, &prf_type) != PR_SUCCESS) { goto failure; } /* Handle Data Parameters. */ if (kbkdf_GetDataParameters(env, this, this_class, &num_data_params, &data_params) != PR_SUCCESS) { goto failure; } /* Handle Additional Derived Keys. */ if (kbkdf_GetAdditionalDerivedKeys(env, this, this_class, &num_additional_keys, &additional_keys) != PR_SUCCESS) { goto failure; } /* Handle Initial Value. */ if (kbkdf_GetInitialValue(env, this, this_class, &initial_value_length, &initial_value) != PR_SUCCESS) { goto failure; } /* Place the values in the actual KDF params struct. */ kdf_params = calloc(1, sizeof(CK_SP800_108_FEEDBACK_KDF_PARAMS)); kdf_params->prfType = prf_type; kdf_params->ulNumberOfDataParams = num_data_params; kdf_params->pDataParams = data_params; kdf_params->ulAdditionalDerivedKeys = num_additional_keys; kdf_params->pAdditionalDerivedKeys = additional_keys; kdf_params->ulIVLen = initial_value_length; kdf_params->pIV = initial_value; /* Place it back into this NativeEnclosure. */ params_obj = JSS_PR_wrapStaticVoidPointer(env, (void **)&kdf_params); if (params_obj == NULL) { goto failure; } if (JSS_PR_StoreNativeEnclosure(env, this, params_obj, sizeof(CK_SP800_108_FEEDBACK_KDF_PARAMS)) != PR_SUCCESS) { goto failure; } return; failure: if (data_params != NULL) { memset(data_params, 0, sizeof(CK_PRF_DATA_PARAM) * num_data_params); free(data_params); } if (additional_keys != NULL) { memset(additional_keys, 0, sizeof(CK_DERIVED_KEY) * num_additional_keys); free(additional_keys); } if (initial_value != NULL) { memset(initial_value, 0, sizeof(CK_BYTE) * initial_value_length); free(initial_value); } if (kdf_params != NULL) { memset(kdf_params, 0, sizeof(CK_SP800_108_FEEDBACK_KDF_PARAMS)); free(kdf_params); } } JNIEXPORT void JNICALL Java_org_mozilla_jss_crypto_KBKDFFeedbackParams_releaseNativeResourcesInternal(JNIEnv *env, jobject this) { jobject ptr_object = NULL; CK_SP800_108_FEEDBACK_KDF_PARAMS_PTR kdf_params = NULL; jlong params_length; PR_ASSERT(env != NULL && this != NULL); if (JSS_PR_LoadNativeEnclosure(env, this, &ptr_object, ¶ms_length) != PR_SUCCESS) { return; } if (JSS_PR_getStaticVoidRef(env, ptr_object, (void **)&kdf_params) != PR_SUCCESS || kdf_params == NULL) { return; } PR_ASSERT(params_length == sizeof(CK_SP800_108_FEEDBACK_KDF_PARAMS)); if (kdf_params->ulNumberOfDataParams != 0 && kdf_params->pDataParams != NULL) { memset(kdf_params->pDataParams, 0, sizeof(CK_PRF_DATA_PARAM) * kdf_params->ulNumberOfDataParams); free(kdf_params->pDataParams); } if (kdf_params->ulIVLen != 0 && kdf_params->pIV != NULL) { memset(kdf_params->pIV, 0, sizeof(CK_BYTE) * kdf_params->ulIVLen); free(kdf_params->pIV); } if (kdf_params->ulAdditionalDerivedKeys != 0 && kdf_params->pAdditionalDerivedKeys != NULL) { memset(kdf_params->pAdditionalDerivedKeys, 0, sizeof(CK_DERIVED_KEY) * kdf_params->ulAdditionalDerivedKeys); free(kdf_params->pAdditionalDerivedKeys); } memset(kdf_params, 0, params_length); free(kdf_params); } /* ===== KBKDF Double Pipeline Parameters ===== */ JNIEXPORT void JNICALL Java_org_mozilla_jss_crypto_KBKDFPipelineParams_acquireNativeResourcesInternal(JNIEnv *env, jobject this) { /* Counter and Double Pipeline modes have the same parameter struct. * This allows us to implement this call via the corresponding call for * Counter mode. */ Java_org_mozilla_jss_crypto_KBKDFCounterParams_acquireNativeResourcesInternal(env, this); } JNIEXPORT void JNICALL Java_org_mozilla_jss_crypto_KBKDFPipelineParams_releaseNativeResourcesInternal(JNIEnv *env, jobject this) { /* Counter and Double Pipeline modes have the same parameter struct. * This allows us to implement this call via the corresponding call for * Counter mode. */ Java_org_mozilla_jss_crypto_KBKDFCounterParams_releaseNativeResourcesInternal(env, this); } #endif jss-5.0.0/src/main/java/org/mozilla/jss/crypto/KBKDFByteArrayParam.java000066400000000000000000000040411412550063600256150ustar00rootroot00000000000000package org.mozilla.jss.crypto; import java.util.Arrays; import org.mozilla.jss.pkcs11.PKCS11Constants; /** * A KBKDF Byte Array Parameter is a type of KBKDF Data Parameter that * contains a single byte array that gets passed to the KBKDF to be inserted * into the PRF input stream. */ public class KBKDFByteArrayParam extends KBKDFDataParameter { private byte[] data; public KBKDFByteArrayParam() { super(PKCS11Constants.CK_SP800_108_BYTE_ARRAY); } public KBKDFByteArrayParam(byte[] data) throws IllegalArgumentException { this(); setByteArray(data); } public void setByteArray(byte[] data) throws IllegalArgumentException { if (data == null) { throw new IllegalArgumentException("Expected non-null byte array!"); } this.data = Arrays.copyOf(data, data.length); } /** * Zero out the copied contents of the byte array. * * Call this method when the contents of this byte array parameter are * sensitive and they're done being used. Note that this isn't called * during close() as a given byte array parameter may be used multiple * times in different KBKDF calls. */ public void zeroByteArray() { if (data == null) { return; } for (int i = 0; i < data.length; i++) { data[i] = 0; } } @Override protected void acquireNativeResources() throws Exception { if (data == null || data.length == 0) { String msg = "Expected non-null byte array in "; msg += "KBKDFByteArrayParam but was null! Call setByteArray "; msg += "to provide a byte array."; throw new RuntimeException(msg); } acquireNativeResourcesInternal(); } @Override protected void releaseNativeResources() throws Exception { releaseNativeResourcesInternal(); } private native void acquireNativeResourcesInternal() throws Exception; private native void releaseNativeResourcesInternal() throws Exception; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/KBKDFCounterParams.java000066400000000000000000000061501412550063600255200ustar00rootroot00000000000000package org.mozilla.jss.crypto; import org.mozilla.jss.pkcs11.PKCS11Constants; public class KBKDFCounterParams extends KBKDFParameterSpec { public KBKDFCounterParams() { } @Override protected void validateParameters() throws IllegalArgumentException { if (prfKey == null) { String msg = "Required parameter KDF key was never set."; throw new IllegalArgumentException(msg); } if (prf != PKCS11Constants.CKM_SHA_1_HMAC && prf != PKCS11Constants.CKM_SHA256_HMAC && prf != PKCS11Constants.CKM_SHA384_HMAC && prf != PKCS11Constants.CKM_SHA512_HMAC && prf != PKCS11Constants.CKM_AES_CMAC) { String msg = "Expected Pseudo-Random Function to be SHA1-HMAC, "; msg += "SHA2-HMAC, or AES-CMAC, but got unknown PKCS#11 "; msg += "constant: " + prf; throw new IllegalArgumentException(msg); } if (params == null || params.length == 0) { String msg = "Expected non-null, non-zero length array of KDF "; msg += "parameters."; throw new IllegalArgumentException(msg); } int index = 0; for (KBKDFDataParameter param : params) { if (param instanceof KBKDFOptionalCounterParam) { String msg = "Got unexpected data parameter at index " + index; msg += ": KBKDF Optional Counter Parameter is forbidden from "; msg += "use with Counter mode KBKDF."; throw new IllegalArgumentException(msg); } if (param instanceof KBKDFIterationVariableParam) { KBKDFIterationVariableParam kivp = (KBKDFIterationVariableParam) param; if (kivp.widthInBits == -1) { String msg = "Got unexpected data in KBKDF Iteration "; msg += "Variable Parameter at index " + index + ": "; msg += "Expected valid counter specification, but got "; msg += "widthInBits of -1. Call setCounterSpec(...) "; msg += "before using this parameter."; throw new IllegalArgumentException(msg); } } if (param instanceof KBKDFDKMLengthParam) { KBKDFDKMLengthParam kdlp = (KBKDFDKMLengthParam) param; if (kdlp.widthInBits == 0) { String msg = "Got unexpected data in KBKDF DKM Length "; msg += "Parameter at index " + index + ": Expected valid "; msg += "length specification, but got widthInBits of 0. "; msg += "Call setLngthSpec(...) before using this "; msg += "parameter."; throw new IllegalArgumentException(msg); } } // Nothing to validate for byte array parameters. index += 1; } } @Override protected native void acquireNativeResourcesInternal() throws Exception; @Override protected native void releaseNativeResourcesInternal() throws Exception; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/KBKDFDKMLengthParam.java000066400000000000000000000030571412550063600254760ustar00rootroot00000000000000package org.mozilla.jss.crypto; import org.mozilla.jss.pkcs11.PKCS11Constants; /** * A KBKDF Optional Counter Parameter is a type of KBKDF Data Parameter that * describes the optional counter variable for Feedback and Pipeline KBKDFs. * * Note that this parameter is illegal in Counter Mode. */ public class KBKDFDKMLengthParam extends KBKDFDataParameter { protected long lengthMethod = 1; protected boolean littleEndian = false; protected long widthInBits = 0; public KBKDFDKMLengthParam() { super(PKCS11Constants.CK_SP800_108_DKM_LENGTH); } public KBKDFDKMLengthParam(long lengthMethod, boolean littleEndian, long widthInBits) throws IllegalArgumentException { this(); setLengthSpec(lengthMethod, littleEndian, widthInBits); } public void setLengthSpec(long lengthMethod, boolean littleEndian, long widthInBits) throws IllegalArgumentException { if (widthInBits < 8 || widthInBits > 64) { throw new IllegalArgumentException("Expected to have width between 8 and 64, but was " + widthInBits); } if ((widthInBits % 8) != 0) { throw new IllegalArgumentException("Expected width to be an even number of bytes, but was " + widthInBits); } this.lengthMethod = lengthMethod; this.littleEndian = littleEndian; this.widthInBits = widthInBits; } @Override protected native void acquireNativeResources() throws Exception; @Override protected native void releaseNativeResources() throws Exception; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/KBKDFDataParameter.java000066400000000000000000000006341412550063600254500ustar00rootroot00000000000000package org.mozilla.jss.crypto; import org.mozilla.jss.util.NativeEnclosure; /** * A KBKDF Data Parameter is a structure of type CK_PRF_DATA_PARAM, with * three members: a type, a pointer to its data, and the size of the data * field. */ public abstract class KBKDFDataParameter extends NativeEnclosure { public long type; public KBKDFDataParameter(long type) { this.type = type; } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/KBKDFDerivedKey.java000066400000000000000000000070461412550063600247750ustar00rootroot00000000000000package org.mozilla.jss.crypto; import java.security.InvalidKeyException; import java.util.ArrayList; import java.util.Arrays; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import org.mozilla.jss.pkcs11.attrs.CKAttribute; import org.mozilla.jss.util.NativeEnclosure; /** * Class for supporting additional derived keys from PKCS#11 v3.0's * SP800-108 KBKDF implementation. */ public class KBKDFDerivedKey extends NativeEnclosure { private CKAttribute[] attrs; private long handle; public KBKDFDerivedKey() { } public KBKDFDerivedKey(CKAttribute[] attrs) throws IllegalArgumentException { setAttributes(attrs); } public void setAttributes(CKAttribute[] attrs) throws IllegalArgumentException { if (attrs == null) { String msg = "Expected populated array of CKAttributes, but "; msg += "was null."; throw new IllegalArgumentException(msg); } this.attrs = attrs; } public void addAttribute(CKAttribute attr) throws IllegalArgumentException { if (attr == null) { String msg = "Expected non-null CKAttribute, but was null."; throw new IllegalArgumentException(msg); } ArrayList ck_attrs; if (attrs == null) { ck_attrs = new ArrayList(1); } else { ck_attrs = new ArrayList(Arrays.asList(attrs)); } ck_attrs.add(attr); this.attrs = ck_attrs.toArray(new CKAttribute[ck_attrs.size()]); } @Override protected void acquireNativeResources() throws Exception { if (attrs == null) { String msg = "Expected non-null attributes when trying to "; msg += "acquire native resources. Call setAttributes(...) "; msg += "or addAttribute(...) before calling open()."; throw new IllegalArgumentException(msg); } for (CKAttribute attr : attrs) { attr.open(); } acquireNativeResourcesInternal(); } @Override protected void releaseNativeResources() throws Exception { if (attrs != null) { for (CKAttribute attr : attrs) { attr.close(); } } releaseNativeResourcesInternal(); } public SecretKey getKey(SecretKey parent, long mech, boolean temporary) throws Exception { SecretKeyFactory skf = SecretKeyFactory.getInstance(parent.getAlgorithm(), "Mozilla-JSS"); SecretKey translated = skf.translateKey(parent); SymmetricKey unwrapped = null; if (translated instanceof SymmetricKey) { unwrapped = (SymmetricKey) translated; } else if (translated instanceof SecretKeyFacade) { unwrapped = ((SecretKeyFacade) translated).key; } else { String msg = "Expected key to become an instance of "; msg += "org.mozilla.jss.crypto.SymmetricKey or "; msg += "org.mozilla.jss.crypto.SecretKeyFacade after "; msg += "translation, but got: "; msg += translated.getClass().getName(); throw new InvalidKeyException(msg); } SymmetricKey key = getKeyFromHandle(unwrapped, mech, temporary); return new SecretKeyFacade(key); } private native SymmetricKey getKeyFromHandle(SymmetricKey parentKey, long mech, boolean temporary) throws Exception; protected native void acquireNativeResourcesInternal() throws Exception; protected native void releaseNativeResourcesInternal() throws Exception; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/KBKDFFeedbackParams.java000066400000000000000000000105471412550063600255720ustar00rootroot00000000000000package org.mozilla.jss.crypto; import java.util.Arrays; import org.mozilla.jss.pkcs11.PKCS11Constants; public class KBKDFFeedbackParams extends KBKDFParameterSpec { private byte[] initial_value; public KBKDFFeedbackParams() { } public void setInitialValue(byte[] iv) throws IllegalArgumentException { if (iv == null) { String msg = "Expected non-null initial value!"; throw new IllegalArgumentException(msg); } this.initial_value = Arrays.copyOf(iv, iv.length); } /** * Zero out the copiend contents of the initial value. * * Call this method when the contents of the initial value are sensitive * and they're done being used. Note that this isn't called during * close() as a given KBKDFParameterSpec instance may be reused, updating * relevant parameters between calls. */ public void zeroInitialValue() { if (initial_value == null) { return; } for (int i = 0; i < initial_value.length; i++) { initial_value[i] = 0; } } @Override protected void validateParameters() throws IllegalArgumentException { if (prfKey == null) { String msg = "Required parameter KDF key was never set."; throw new IllegalArgumentException(msg); } if (prf != PKCS11Constants.CKM_SHA_1_HMAC && prf != PKCS11Constants.CKM_SHA256_HMAC && prf != PKCS11Constants.CKM_SHA384_HMAC && prf != PKCS11Constants.CKM_SHA512_HMAC && prf != PKCS11Constants.CKM_AES_CMAC) { String msg = "Expected Pseudo-Random Function to be SHA1-HMAC, "; msg += "SHA2-HMAC, or AES-CMAC, but got unknown PKCS#11 "; msg += "constant: " + prf; throw new IllegalArgumentException(msg); } if (params == null || params.length == 0) { String msg = "Expected non-null, non-zero length array of KDF "; msg += "parameters."; throw new IllegalArgumentException(msg); } int index = 0; for (KBKDFDataParameter param : params) { if (param instanceof KBKDFOptionalCounterParam) { KBKDFOptionalCounterParam kocp = (KBKDFOptionalCounterParam) param; if (kocp.widthInBits == -1) { String msg = "Got unexpected data in KBKDF Optional "; msg += "Counter Parameter at index " + index + ": "; msg += "Expected valid counter specification, but got "; msg += "widthInBits of -1. Call setCounterSpec(...) "; msg += "before using this parameter."; throw new IllegalArgumentException(msg); } } if (param instanceof KBKDFIterationVariableParam) { KBKDFIterationVariableParam kivp = (KBKDFIterationVariableParam) param; if (kivp.widthInBits != -1) { String msg = "Got unexpected data in KBKDF Iteration "; msg += "Variable Parameter at index " + index + ": "; msg += "Expected empty counter specification, but got "; msg += "widthInBits of " + kivp.widthInBits + ". Call "; msg += "the no argument constructor instead to use this "; msg += "parameter."; throw new IllegalArgumentException(msg); } } if (param instanceof KBKDFDKMLengthParam) { KBKDFDKMLengthParam kdlp = (KBKDFDKMLengthParam) param; if (kdlp.widthInBits == 0) { String msg = "Got unexpected data in KBKDF DKM Length "; msg += "Parameter at index " + index + ": Expected valid "; msg += "length specification, but got widthInBits of 0. "; msg += "Call setLngthSpec(...) before using this "; msg += "parameter."; throw new IllegalArgumentException(msg); } } // Nothing to validate for byte array parameters. index += 1; } } @Override protected native void acquireNativeResourcesInternal() throws Exception; @Override protected native void releaseNativeResourcesInternal() throws Exception; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/KBKDFIterationVariableParam.java000066400000000000000000000034531412550063600273250ustar00rootroot00000000000000package org.mozilla.jss.crypto; import org.mozilla.jss.pkcs11.PKCS11Constants; /** * A KBKDF Iteration Variable Parameter is a type of KBKDF Data Parameter that * either references the counter variable or otherwise is a pointer to the * output of the previous PRF invocation. * * Note that in when used with Counter Mode KBKDF, this parameter must be * initialized with the two argument constructor. In other KBKDF modes, * in particular, Feedback and Pipeline modes, this must be initialized with * the no argument constructor. To add an optional counter to the PRF input * stream under Feedback and Pipeline modes, use KBKDFOptionalCounterParam * instead. */ public class KBKDFIterationVariableParam extends KBKDFDataParameter { protected boolean littleEndian = false; protected long widthInBits = -1; public KBKDFIterationVariableParam() { super(PKCS11Constants.CK_SP800_108_ITERATION_VARIABLE); } public KBKDFIterationVariableParam(boolean littleEndian, long widthInBits) throws IllegalArgumentException { this(); setCounterSpec(littleEndian, widthInBits); } public void setCounterSpec(boolean littleEndian, long widthInBits) throws IllegalArgumentException { if (widthInBits < 8 || widthInBits > 64) { throw new IllegalArgumentException("Expected to have width between 8 and 64, but was " + widthInBits); } if ((widthInBits % 8) != 0) { throw new IllegalArgumentException("Expected width to be an even number of bytes, but was " + widthInBits); } this.littleEndian = littleEndian; this.widthInBits = widthInBits; } @Override protected native void acquireNativeResources() throws Exception; @Override protected native void releaseNativeResources() throws Exception; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/KBKDFOptionalCounterParam.java000066400000000000000000000026561412550063600270520ustar00rootroot00000000000000package org.mozilla.jss.crypto; import org.mozilla.jss.pkcs11.PKCS11Constants; /** * A KBKDF Optional Counter Parameter is a type of KBKDF Data Parameter that * describes the optional counter variable for Feedback and Pipeline KBKDFs. * * Note that this parameter is illegal in Counter Mode. */ public class KBKDFOptionalCounterParam extends KBKDFDataParameter { protected boolean littleEndian = false; protected long widthInBits = 0; public KBKDFOptionalCounterParam() { super(PKCS11Constants.CK_SP800_108_OPTIONAL_COUNTER); } public KBKDFOptionalCounterParam(boolean littleEndian, long widthInBits) throws IllegalArgumentException { this(); setCounterSpec(littleEndian, widthInBits); } public void setCounterSpec(boolean littleEndian, long widthInBits) throws IllegalArgumentException { if (widthInBits < 8 || widthInBits > 64) { throw new IllegalArgumentException("Expected to have width between 8 and 64, but was " + widthInBits); } if ((widthInBits % 8) != 0) { throw new IllegalArgumentException("Expected width to be an even number of bytes, but was " + widthInBits); } this.littleEndian = littleEndian; this.widthInBits = widthInBits; } @Override protected native void acquireNativeResources() throws Exception; @Override protected native void releaseNativeResources() throws Exception; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/KBKDFParameterSpec.java000066400000000000000000000174641412550063600255020ustar00rootroot00000000000000package org.mozilla.jss.crypto; import java.security.InvalidKeyException; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.KeySpec; import java.util.ArrayList; import java.util.Arrays; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import org.mozilla.jss.pkcs11.PK11SymKey; import org.mozilla.jss.util.NativeEnclosure; public abstract class KBKDFParameterSpec extends NativeEnclosure implements AlgorithmParameterSpec, KeySpec { /* Need access from outside; no real protections in setters outside * of additional input types. */ public PK11SymKey prfKey; public long derivedKeyAlgorithm; public int keySize; protected long prf; protected KBKDFDataParameter[] params; protected KBKDFDerivedKey[] additional_keys; /** * Set the underlying pseudo-random function from a PKCS11Algorithm enum * value. */ public void setPRF(PKCS11Algorithm prf) throws IllegalArgumentException { this.prf = prf.getValue(); } /** * Set the underlying pseudo-random function from a DigestAlgorithm * (HMACAlgorithm or CMACAlgorithm) instance. */ public void setPRF(DigestAlgorithm prf) throws IllegalArgumentException { if (!(prf instanceof HMACAlgorithm) && !(prf instanceof CMACAlgorithm)) { String msg = "Unknown pseudo-random function type: expected "; msg += "either HMAC or CMAC algorithms. Got: "; msg += prf.getClass().getName(); throw new IllegalArgumentException(msg); } this.prf = prf.getEnum().getValue(); } /** * Set the underlying pseudo-random function from a PKCS#11 constant; * see org.mozilla.jss.pkcs11.PKCS11Constants for permitted values. */ public void setPRF(long prf) { this.prf = prf; } /** * Set the base key used with the underlying PRF. * * Must be importable to a JSS SymmetricKey or SecretKeyFacade. */ public void setPRFKey(SecretKey key) throws InvalidKeyException { if (key instanceof PK11SymKey) { prfKey = (PK11SymKey) key; return; } if (key instanceof SecretKeyFacade) { setPRFKey(((SecretKeyFacade) key).key); return; } try { SecretKeyFactory skf = SecretKeyFactory.getInstance(key.getAlgorithm(), "Mozilla-JSS"); SecretKey translated = skf.translateKey(key); if (translated instanceof SymmetricKey) { setPRFKey(translated); return; } if (translated instanceof SecretKeyFacade) { setPRFKey(((SecretKeyFacade) translated).key); return; } String msg = "Expected key to become an instance of "; msg += "org.mozilla.jss.crypto.SymmetricKey or "; msg += "org.mozilla.jss.crypto.SecretKeyFacade after "; msg += "translation, but got: "; msg += translated.getClass().getName(); throw new InvalidKeyException(msg); } catch (Exception excep) { throw new InvalidKeyException("Unable to import key: " + excep.getMessage(), excep); } } /** * Set the algorithm for the derived key from a PKCS11Algorithm enum value. */ public void setDerivedKeyAlgorithm(PKCS11Algorithm algo) throws IllegalArgumentException { if (algo == null) { String msg = "Expected non-null PKCS11Algorithm value, but was null."; throw new IllegalArgumentException(msg); } derivedKeyAlgorithm = algo.getValue(); } /** * Sets the algorithm for the derived key from a PKCS#11 value; see * org.mozilla.jss.pkcs11.PKCS11Constants for constant values. */ public void setDerivedKeyAlgorithm(long algo) throws IllegalArgumentException { derivedKeyAlgorithm = algo; } /** * Set the size of the derived key. * * If zero, will attempt to use the derived key algorithm's default key * size. */ public void setKeySize(int keySize) { this.keySize = keySize; } /** * Set parameters for key derivation. * * This overwrites all existing parameters. Note that params cannot be * NULL. */ public void setParameters(KBKDFDataParameter[] params) throws IllegalArgumentException { if (params == null) { String msg = "Expected populated array of KBKDFDataParameters, "; msg += "but was null."; throw new IllegalArgumentException(msg); } this.params = params; } /** * Appends (to the end) a new data parameter. */ public void addParameter(KBKDFDataParameter param) throws IllegalArgumentException { if (param == null) { String msg = "Expected non-null instance of KBKDFDataParameters, "; msg += "but was null."; throw new IllegalArgumentException(msg); } ArrayList data_params; if (this.params == null) { data_params = new ArrayList(1); } else { data_params = new ArrayList(Arrays.asList(this.params)); } data_params.add(param); this.params = data_params.toArray(new KBKDFDataParameter[data_params.size()]); } /** * Set an array of additional derived keys. */ public void setAdditionalDerivedKeys(KBKDFDerivedKey[] additional_keys) throws IllegalArgumentException { if (additional_keys == null) { String msg = "Expected populated array of KBKDFDerivedKey, "; msg += "but was null."; throw new IllegalArgumentException(msg); } this.additional_keys = additional_keys; } /** * Append (to the end) a new derived key. */ public void addAdditionalDerivedKey(KBKDFDerivedKey derived_key) throws IllegalArgumentException { if (derived_key == null) { String msg = "Expected non-null instance of KBKDFDerivedKey, "; msg += "but was null."; throw new IllegalArgumentException(msg); } ArrayList keys; if (additional_keys == null) { keys = new ArrayList(1); } else { keys = new ArrayList(Arrays.asList(additional_keys)); } keys.add(derived_key); additional_keys = keys.toArray(new KBKDFDerivedKey[keys.size()]); } @Override protected void acquireNativeResources() throws Exception { validateParameters(); if (params != null) { for (KBKDFDataParameter param : params) { param.open(); } } if (additional_keys != null) { for (KBKDFDerivedKey key : additional_keys) { key.open(); } } acquireNativeResourcesInternal(); } @Override protected void releaseNativeResources() throws Exception { if (additional_keys != null) { for (KBKDFDerivedKey key : additional_keys) { key.close(); } } if (params != null) { for (KBKDFDataParameter param : params) { param.close(); } } releaseNativeResourcesInternal(); } protected abstract void acquireNativeResourcesInternal() throws Exception; protected abstract void releaseNativeResourcesInternal() throws Exception; /** * Validate all class members prior to acquiring native resources. * * This is implemented by the derived KBKDF modes in an effort to give * useful exceptions before derivation, instead of vague errors during * derivation. */ protected abstract void validateParameters() throws IllegalArgumentException; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/KBKDFPipelineParams.java000066400000000000000000000067211412550063600256520ustar00rootroot00000000000000package org.mozilla.jss.crypto; import org.mozilla.jss.pkcs11.PKCS11Constants; public class KBKDFPipelineParams extends KBKDFParameterSpec { public KBKDFPipelineParams() { } @Override protected void validateParameters() throws IllegalArgumentException { if (prfKey == null) { String msg = "Required parameter KDF key was never set."; throw new IllegalArgumentException(msg); } if (prf != PKCS11Constants.CKM_SHA_1_HMAC && prf != PKCS11Constants.CKM_SHA256_HMAC && prf != PKCS11Constants.CKM_SHA384_HMAC && prf != PKCS11Constants.CKM_SHA512_HMAC && prf != PKCS11Constants.CKM_AES_CMAC) { String msg = "Expected Pseudo-Random Function to be SHA1-HMAC, "; msg += "SHA2-HMAC, or AES-CMAC, but got unknown PKCS#11 "; msg += "constant: " + prf; throw new IllegalArgumentException(msg); } if (params == null || params.length == 0) { String msg = "Expected non-null, non-zero length array of KDF "; msg += "parameters."; throw new IllegalArgumentException(msg); } int index = 0; for (KBKDFDataParameter param : params) { if (param instanceof KBKDFOptionalCounterParam) { KBKDFOptionalCounterParam kocp = (KBKDFOptionalCounterParam) param; if (kocp.widthInBits == -1) { String msg = "Got unexpected data in KBKDF Optional "; msg += "Counter Parameter at index " + index + ": "; msg += "Expected valid counter specification, but got "; msg += "widthInBits of -1. Call setCounterSpec(...) "; msg += "before using this parameter."; throw new IllegalArgumentException(msg); } } if (param instanceof KBKDFIterationVariableParam) { KBKDFIterationVariableParam kivp = (KBKDFIterationVariableParam) param; if (kivp.widthInBits != -1) { String msg = "Got unexpected data in KBKDF Iteration "; msg += "Variable Parameter at index " + index + ": "; msg += "Expected empty counter specification, but got "; msg += "widthInBits of " + kivp.widthInBits + ". Call "; msg += "the no argument constructor instead to use this "; msg += "parameter."; throw new IllegalArgumentException(msg); } } if (param instanceof KBKDFDKMLengthParam) { KBKDFDKMLengthParam kdlp = (KBKDFDKMLengthParam) param; if (kdlp.widthInBits == 0) { String msg = "Got unexpected data in KBKDF DKM Length "; msg += "Parameter at index " + index + ": Expected valid "; msg += "length specification, but got widthInBits of 0. "; msg += "Call setLngthSpec(...) before using this "; msg += "parameter."; throw new IllegalArgumentException(msg); } } // Nothing to validate for byte array parameters. index += 1; } } @Override protected native void acquireNativeResourcesInternal() throws Exception; @Override protected native void releaseNativeResourcesInternal() throws Exception; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/KeyAlreadyImportedException.java000066400000000000000000000016151412550063600276110ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; /** * This exception is thrown if the user tries to import a * key which is already in the specified token */ public class KeyAlreadyImportedException extends java.lang.Exception { private static final long serialVersionUID = 1L; public KeyAlreadyImportedException() {} public KeyAlreadyImportedException(String mesg) { super(mesg); } public KeyAlreadyImportedException(String mesg, Throwable cause) { super(mesg, cause); } public KeyAlreadyImportedException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(mesg, cause, enableSuppression, writableStackTrace); } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/KeyGenAlgorithm.java000066400000000000000000000204241412550063600252240ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.NoSuchAlgorithmException; import java.util.Hashtable; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; /** * Algorithms that can be used for generating symmetric keys. */ public class KeyGenAlgorithm extends Algorithm { protected static interface KeyStrengthValidator { public boolean isValidKeyStrength(int strength); } protected static class FixedKeyStrengthValidator implements KeyStrengthValidator { private int strength; public FixedKeyStrengthValidator(int strength) { this.strength = strength; } @Override public boolean isValidKeyStrength(int strength) { return this.strength == strength; } } protected static class AnyKeyStrengthValidator implements KeyStrengthValidator { @Override public boolean isValidKeyStrength(int strength) { return true; } } protected KeyGenAlgorithm(int oidTag, String name, KeyStrengthValidator keyStrengthValidator, OBJECT_IDENTIFIER oid, Class paramClass) { super(oidTag, name, oid, paramClass); this.keyStrengthValidator = keyStrengthValidator; if (oid != null) { oidMap.put(oid, this); } } /////////////////////////////////////////////////////////////////////// // OIDs /////////////////////////////////////////////////////////////////////// private static final OBJECT_IDENTIFIER PKCS5 = OBJECT_IDENTIFIER.PKCS5; private static final OBJECT_IDENTIFIER PKCS12_PBE = OBJECT_IDENTIFIER.PKCS12.subBranch(1); /////////////////////////////////////////////////////////////////////// // OID mapping /////////////////////////////////////////////////////////////////////// private static Hashtable oidMap = new Hashtable<>(); public static KeyGenAlgorithm fromOID(OBJECT_IDENTIFIER oid) throws NoSuchAlgorithmException { Object alg = oidMap.get(oid); if (alg == null) { throw new NoSuchAlgorithmException(oid.toString()); } else { return (KeyGenAlgorithm) alg; } } private KeyStrengthValidator keyStrengthValidator; /** * @param strength Key strength. * @return true if the given strength is valid for this * key generation algorithm. Note that PBE algorithms require * PBEParameterSpecs rather than strengths. It is the responsibility * of the caller to verify this. */ public boolean isValidStrength(int strength) { return keyStrengthValidator.isValidKeyStrength(strength); } ////////////////////////////////////////////////////////////// public static final KeyGenAlgorithm GENERIC_SECRET = new KeyGenAlgorithm( CKM_GENERIC_SECRET_KEY_GEN, "GenericSecret", new AnyKeyStrengthValidator(), null, null); ////////////////////////////////////////////////////////////// public static final KeyGenAlgorithm DES = new KeyGenAlgorithm( CKM_DES_KEY_GEN, "DES", new FixedKeyStrengthValidator(56), null, null); ////////////////////////////////////////////////////////////// public static final KeyGenAlgorithm DES3 = new KeyGenAlgorithm( CKM_DES3_KEY_GEN, "DESede", new FixedKeyStrengthValidator(168), null, null); public static final KeyGenAlgorithm DESede = DES3; ////////////////////////////////////////////////////////////// public static final KeyGenAlgorithm RC4 = new KeyGenAlgorithm( CKM_RC4_KEY_GEN, "RC4", new AnyKeyStrengthValidator(), null, null); ////////////////////////////////////////////////////////////// public static final KeyGenAlgorithm PBA_SHA1_HMAC = new KeyGenAlgorithm( CKM_PBA_SHA1_WITH_SHA1_HMAC, "PBA/SHA1/HMAC", new FixedKeyStrengthValidator(160), null, PBEKeyGenParams.class); public static final KeyGenAlgorithm SHA1_HMAC = new KeyGenAlgorithm( CKM_SHA_1_HMAC, "SHA1/HMAC", new FixedKeyStrengthValidator(160), null, null); public static final KeyGenAlgorithm SHA256_HMAC = new KeyGenAlgorithm( CKM_SHA256_HMAC, "SHA256/HMAC", new FixedKeyStrengthValidator(256), null, null); public static final KeyGenAlgorithm SHA384_HMAC = new KeyGenAlgorithm( CKM_SHA384_HMAC, "SHA384/HMAC", new FixedKeyStrengthValidator(384), null, null); public static final KeyGenAlgorithm SHA512_HMAC = new KeyGenAlgorithm( CKM_SHA512_HMAC, "SHA512/HMAC", new FixedKeyStrengthValidator(512), null, null); ////////////////////////////////////////////////////////////// public static final KeyGenAlgorithm AES = new KeyGenAlgorithm( CKM_AES_KEY_GEN, "AES", new KeyStrengthValidator() { @Override public boolean isValidKeyStrength(int strength) { return strength == 128 || strength == 192 || strength == 256; } }, null, null); ////////////////////////////////////////////////////////////// public static final KeyGenAlgorithm RC2 = new KeyGenAlgorithm( CKM_RC2_KEY_GEN, "RC2", new KeyStrengthValidator() { @Override public boolean isValidKeyStrength(int strength) { // Allow any key of size between 1 byte and 128 bytes return strength >= 8 && strength <= (128 * 8); } }, null, null); ////////////////////////////////////////////////////////////// /////////////// GENERIC KBKDFs: NIST SP800-108 /////////////// ////////////////////////////////////////////////////////////// public static final KeyGenAlgorithm SP800_108_COUNTER_KDF = new KeyGenAlgorithm( CKM_SP800_108_COUNTER_KDF, "SP800_108_COUNTER_KDF", new AnyKeyStrengthValidator(), null, KBKDFCounterParams.class); public static final KeyGenAlgorithm SP800_108_FEEDBACK_KDF = new KeyGenAlgorithm( CKM_SP800_108_FEEDBACK_KDF, "SP800_108_FEEDBACK_KDF", new AnyKeyStrengthValidator(), null, KBKDFFeedbackParams.class); public static final KeyGenAlgorithm SP800_108_DOUBLE_PIPELINE_KDF = new KeyGenAlgorithm( CKM_SP800_108_DOUBLE_PIPELINE_KDF, "SP800_108_DOUBLE_PIPELINE_KDF", new AnyKeyStrengthValidator(), null, KBKDFPipelineParams.class); ////////////////////////////////////////////////////////////// //////////// Data KBKDFs: NSS-only NIST SP800-108 //////////// ////////////////////////////////////////////////////////////// public static final KeyGenAlgorithm NSS_SP800_108_COUNTER_KDF_DERIVE_DATA = new KeyGenAlgorithm( CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA, "NSS_SP800_108_COUNTER_KDF_DERIVE_DATA", new AnyKeyStrengthValidator(), null, KBKDFCounterParams.class); public static final KeyGenAlgorithm NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA = new KeyGenAlgorithm( CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA, "NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA", new AnyKeyStrengthValidator(), null, KBKDFFeedbackParams.class); public static final KeyGenAlgorithm NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA = new KeyGenAlgorithm( CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA, "NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA", new AnyKeyStrengthValidator(), null, KBKDFPipelineParams.class); } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/KeyGenerator.java000066400000000000000000000120531412550063600245710ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.io.CharConversionException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.spec.AlgorithmParameterSpec; /** * Generates symmetric keys for encryption and decryption. */ public interface KeyGenerator { /** * @param strength Key size in bits. Must be evenly divisible by 8. * @throws InvalidAlgorithmParameterException If parameter is invalid. */ public void initialize(int strength) throws InvalidAlgorithmParameterException; public void initialize(AlgorithmParameterSpec parameters) throws InvalidAlgorithmParameterException; /** * @param usages The operations the key will be used for after it is * generated. You have to specify these so that the key can be properly * marked with the operations it supports. Some PKCS #11 tokens require * that a key be marked for an operation before it can perform that * operation. The default is SymmetricKey.Usage.SIGN and * SymmetricKey.Usage.ENCRYPT. */ public void setKeyUsages(SymmetricKey.Usage[] usages); /** * Tells the generator to generate temporary or permanent keys. * Temporary keys are not written permanently to the token. They * are destroyed by the garbage collector. If this method is not * called, the default is temporary keys. * @param temp True to generate temporary key. */ public void temporaryKeys(boolean temp); /** * Tells the generator to generate sensitive or insensitive keys. * Certain attributes of a sensitive key cannot be revealed in * plaintext outside the token. If this method is not called, the * default is token dependent. * @param sensitive True to generate sensitive. */ public void sensitiveKeys(boolean sensitive); /** * Generates a symmetric key. * @return Symmetric key. * @throws IllegalStateException If key generation failed. * @throws TokenException If an error occurred in the token. * @throws CharConversionException If an encoding error occurred. */ public SymmetricKey generate() throws IllegalStateException, TokenException, CharConversionException; /** * Generates an Initialization Vector using a PBE algorithm. * In order to call this method, the algorithm must be a PBE algorithm, * and the KeyGenerator must have been initialized with an instance * of PBEKeyGenParams. * * @return The initialization vector derived from the password and salt * using the PBE algorithm. * @exception IllegalStateException If the algorithm is not a PBE * algorithm, or the KeyGenerator has not been initialized with * an instance of PBEKeyGenParams. * @exception TokenException If an error occurs on the CryptoToken while * generating the IV. * @exception CharConversionException If an encoding error occurred. */ public byte[] generatePBE_IV() throws IllegalStateException, TokenException, CharConversionException; /** * Allows a SymmetricKey to be cloned on a different token. * * @param key Symmetric key. * @return Cloned symmetric key. * @exception SymmetricKey.NotExtractableException If the key material * cannot be extracted from the current token. * @exception InvalidKeyException If the owning token cannot process * the key to be cloned. * @exception TokenException If an error occurred in the token. */ public SymmetricKey clone(SymmetricKey key) throws SymmetricKey.NotExtractableException, InvalidKeyException, TokenException; /** * An interface for converting a password of Java characters into an array * of bytes. This conversion must be performed to provide a byte array * to the low-level crypto engine. The default conversion is UTF8. * Null-termination is not necessary, and indeed is usually incorrect, * since the password is passed to the crypto engine as a byte array, not * a C string. */ public static interface CharToByteConverter { /** * Converts a password of Java characters into a password of * bytes, using some encoding scheme. The input char array must * not be modified. * @param chars Password characters. * @return Password as byte array. * @throws CharConversionException If an error occurred. */ public byte[] convert(char[] chars) throws CharConversionException; } /** * Sets the character to byte converter for passwords. The default * conversion is UTF8 with no null termination. * @param charToByte Character-to-byte converter. */ public void setCharToByteConverter(CharToByteConverter charToByte); } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/KeyPairAlgorithm.java000066400000000000000000000056571412550063600254210ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.NoSuchAlgorithmException; import java.util.Hashtable; /** * Algorithms that can be used for keypair generation. */ public class KeyPairAlgorithm extends Algorithm { protected KeyPairAlgorithm(int oidIndex, String name, Algorithm algFamily) { super(oidIndex, name); this.algFamily = algFamily; nameMap.put(name, this); } /** * Returns the algorithm family for a given key pair generation algorithm. * If a token supports a family and is writable, we can do keypair gen * on the token even if it doesn't support the keypair gen algorithm. * We do this by doing the keypair gen on the internal module and then * moving the key out to the other token. * @return Algorithm family. */ public Algorithm getAlgFamily() { return algFamily; } private static Hashtable nameMap = new Hashtable<>(); /** * Looks up a key pair generation algorithm from its name. The names * are those specified in the JCA spec. For example, "RSA" and "DSA". * * @param algName Algorithm name. * @return Key pair generation algorithm. * @throws NoSuchAlgorithmException If the name of the algorithm is not * recognized as a supported algorithm. */ public static KeyPairAlgorithm fromString(String algName) throws NoSuchAlgorithmException { KeyPairAlgorithm alg = nameMap.get(algName); if( alg == null ) { throw new NoSuchAlgorithmException(); } return alg; } protected Algorithm algFamily; //////////////////////////////////////////////////////////////// // Key-Pair Generation Algorithms //////////////////////////////////////////////////////////////// public static final Algorithm RSAFamily = new Algorithm(SEC_OID_PKCS1_RSA_ENCRYPTION, "RSA"); public static final Algorithm DSAFamily = new Algorithm(SEC_OID_ANSIX9_DSA_SIGNATURE, "DSA"); public static final Algorithm // To support both ECDSA and ECDH, it is best to provide two EC Families; // However, since there is no token that does only CKM_DERIVE to // date, we will just do ECDSA for now as it is sufficient enough today. // This fix will support tokens that do not do ECDH ECFamily = new Algorithm(SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST, "EC"); public static final KeyPairAlgorithm RSA = new KeyPairAlgorithm(CKM_RSA_PKCS_KEY_PAIR_GEN, "RSA", RSAFamily); public static final KeyPairAlgorithm DSA = new KeyPairAlgorithm(CKM_DSA_KEY_PAIR_GEN, "DSA", DSAFamily); public static final KeyPairAlgorithm EC = new KeyPairAlgorithm(CKM_EC_KEY_PAIR_GEN, "EC", ECFamily); } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/KeyPairGenerator.java000066400000000000000000000151511412550063600254070ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidParameterException; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; /** * Generates RSA and DSA key pairs. Each CryptoToken provides a * KeyPairGenerator, which can be used to generate key pairs on that token. * A given token may not support all algorithms, and some tokens may not * support any key pair generation. If a token does not support key pair * generation, the Netscape internal token may do it instead. Call * keygenOnInternalToken to find out if this is happening. * * @see org.mozilla.jss.crypto.CryptoToken#getKeyPairGenerator */ public class KeyPairGenerator { /** * Creates a new key pair generator. KeyPairGenerators should * be obtained by calling CryptoToken.getKeyPairGenerator * instead of calling this constructor. * * @param algorithm The type of keys that the generator will be * used to generate. * @param engine The engine object that provides the implementation for * the class. */ public KeyPairGenerator(KeyPairAlgorithm algorithm, KeyPairGeneratorSpi engine) { this.algorithm = algorithm; this.engine = engine; } /** * Generates a new key pair. * * @return A new key pair. The keys reside on the CryptoToken that * provided this KeyPairGenerator. * @exception TokenException If an error occurs on the CryptoToken * in the process of generating the key pair. */ public java.security.KeyPair genKeyPair() throws TokenException { return engine.generateKeyPair(); } /** * @return The type of key that this generator generates. */ public KeyPairAlgorithm getAlgorithm() { return algorithm; } /** * Initializes the generator with algorithm-specific parameters. * The SecureRandom parameters is ignored. * * @param params Algorithm-specific parameters for the key pair generation. * @param random This parameter is ignored. NSS does not accept * an external source of random numbers. * @exception InvalidAlgorithmParameterException If the parameters are * inappropriate for the type of key pair that is being generated, * or they are not supported by this generator. * @see org.mozilla.jss.crypto.RSAParameterSpec * @see java.security.spec.DSAParameterSpec */ public void initialize(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { engine.initialize(params, random); } /** * Initializes the generator with algorithm-specific parameters. * * @param params Algorithm-specific parameters for the key pair generation. * @exception InvalidAlgorithmParameterException If the parameters are * inappropriate for the type of key pair that is being generated, * or they are not supported by this generator. * @see org.mozilla.jss.crypto.RSAParameterSpec * @see java.security.spec.DSAParameterSpec */ public void initialize(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException { engine.initialize(params, null); } /** * Initializes the generator with the strength of the keys. * The SecureRandom parameter is ignored. * * @param strength The strength of the keys that will be generated. * Usually this is the length of the key in bits. * @param random This parameter is ignored. NSS does not accept * an external source of random numbers. */ public void initialize(int strength, SecureRandom random) { engine.initialize(strength, random); } /** * Initializes the generator with the strength of the keys. * * @param strength The strength of the keys that will be generated. * Usually this is the length of the key in bits. */ public void initialize(int strength) { engine.initialize(strength, null); } /** * @return true if the keypair generation will take place on the * internal token rather than the current token. This will * happen if the token does not support keypair generation * but does support this algorithm and is writable. In this * case the keypair will be generated on the Netscape internal * token and then moved to this token. */ public boolean keygenOnInternalToken() { return engine.keygenOnInternalToken(); } /** * Tells the generator to generate temporary or permanent keypairs. * Temporary keys are not written permanently to the token. They * are destroyed by the garbage collector. If this method is not * called, the default is permanent keypairs. * @param temp True to generate temporary keypairs. */ public void temporaryPairs(boolean temp) { engine.temporaryPairs(temp); } /** * Tells the generator to generate sensitive or insensitive keypairs. * Certain attributes of a sensitive key cannot be revealed in * plaintext outside the token. If this method is not called, the * default depends on the temporaryPairs mode for backward * compatibility. The default is sensitive keypairs if the * temporaryPairs mode is false, or insensitive keypairs if the * temporaryPairs mode is true. * @param sensitive To generate sensitive keypairs. */ public void sensitivePairs(boolean sensitive) { engine.sensitivePairs(sensitive); } /** * Tells the generator to generate extractable or unextractable * keypairs. Extractable keys can be extracted from the token after * wrapping. If this method is not called, the default is token * dependent. * @param extractable True to generate extractable keypairs. */ public void extractablePairs(boolean extractable) { engine.extractablePairs(extractable); } public void setKeyPairUsages(KeyPairGeneratorSpi.Usage[] usages, KeyPairGeneratorSpi.Usage[] usages_mask) { engine.setKeyPairUsages(usages,usages_mask); } public int getCurveCodeByName(String curveName) throws InvalidParameterException { return engine.getCurveCodeByName(curveName); } protected KeyPairAlgorithm algorithm; protected KeyPairGeneratorSpi engine; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/KeyPairGeneratorSpi.java000066400000000000000000000056711412550063600260710ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidParameterException; import java.security.KeyPair; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import org.mozilla.jss.pkcs11.PKCS11Constants; public abstract class KeyPairGeneratorSpi { public KeyPairGeneratorSpi() { } public abstract void initialize(int strength, SecureRandom random); public abstract void initialize(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException; public abstract KeyPair generateKeyPair() throws TokenException; public abstract int getCurveCodeByName(String curveName) throws InvalidParameterException; public abstract void temporaryPairs(boolean temp); public abstract void sensitivePairs(boolean sensitive); public abstract void extractablePairs(boolean extractable); public abstract boolean keygenOnInternalToken(); /** * In PKCS #11, each keypair can be marked with the operations it will * be used to perform. Some tokens require that a key be marked for * an operation before the key can be used to perform that operation; * other tokens don't care. NSS provides a way to specify a set of * flags and a corresponding mask for these flags. If a specific usage * is desired set the value for that usage. If it is not set, let NSS * behave in it's default fashion. If a behavior is desired, also set * that behavior in the mask as well as the flags. * */ public enum Usage { ENCRYPT (PKCS11Constants.CKF_ENCRYPT), DECRYPT (PKCS11Constants.CKF_DECRYPT), SIGN (PKCS11Constants.CKF_SIGN), SIGN_RECOVER (PKCS11Constants.CKF_SIGN_RECOVER), VERIFY (PKCS11Constants.CKF_VERIFY), VERIFY_RECOVER (PKCS11Constants.CKF_VERIFY_RECOVER), WRAP (PKCS11Constants.CKF_WRAP), UNWRAP (PKCS11Constants.CKF_UNWRAP), DERIVE (PKCS11Constants.CKF_DERIVE); private final long value; Usage(long value) { this.value = value; } /** * @deprecated Use ordinal() instead. */ @Deprecated public int getVal() { return ordinal(); } /** * Get PKCS #11 CKF_ value. */ public long value() { return value; } } /** * setKeyPairUsages * @param usages Usages. * @param usages_mask Usages mask. */ public abstract void setKeyPairUsages(KeyPairGeneratorSpi.Usage[] usages, KeyPairGeneratorSpi.Usage[] usages_mask); } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/KeyWrapAlgorithm.java000066400000000000000000000146411412550063600254300ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.NoSuchAlgorithmException; import java.util.Hashtable; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.RC2ParameterSpec; import javax.crypto.spec.OAEPParameterSpec; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; /** * */ public class KeyWrapAlgorithm extends Algorithm { protected KeyWrapAlgorithm(int oidTag, String name, Class paramClass, boolean padded, int blockSize) { super(oidTag, name, null, paramClass); this.padded = padded; this.blockSize = blockSize; if( name != null ) { nameMap.put(name.toLowerCase(), this); } } protected KeyWrapAlgorithm(int oidTag, String name, Class []paramClasses, boolean padded, int blockSize) { super(oidTag, name, null, paramClasses); this.padded = padded; this.blockSize = blockSize; if( name != null ) { nameMap.put(name.toLowerCase(), this); } } private boolean padded; private int blockSize; private static Hashtable nameMap = new Hashtable<>(); public static KeyWrapAlgorithm fromString(String name) throws NoSuchAlgorithmException { Object alg = nameMap.get( name.toLowerCase() ); if( alg == null ) { throw new NoSuchAlgorithmException(); } else { return (KeyWrapAlgorithm) alg; } } public boolean isPadded() { return padded; } public int getBlockSize() { return blockSize; } private static Class[] IVParameterSpecClasses = null; static { IVParameterSpecClasses = new Class[2]; IVParameterSpecClasses[0] = IVParameterSpec.class; IVParameterSpecClasses[1] = IvParameterSpec.class; } public static final KeyWrapAlgorithm DES_ECB = new KeyWrapAlgorithm(SEC_OID_DES_ECB, "DES/ECB", (Class) null, false, 8); public static final KeyWrapAlgorithm DES_CBC = new KeyWrapAlgorithm(SEC_OID_DES_CBC, "DES/CBC", IVParameterSpecClasses, false, 8); public static final KeyWrapAlgorithm DES_CBC_PAD = new KeyWrapAlgorithm(CKM_DES_CBC_PAD, "DES/CBC/Pad", IVParameterSpecClasses, true, 8); public static final KeyWrapAlgorithm DES3_ECB = new KeyWrapAlgorithm(CKM_DES3_ECB, "DES3/ECB", (Class)null, false, 8); public static final KeyWrapAlgorithm DES3_CBC = new KeyWrapAlgorithm(SEC_OID_DES_EDE3_CBC, "DES3/CBC", IVParameterSpecClasses, false, 8); public static final KeyWrapAlgorithm DES3_CBC_PAD = new KeyWrapAlgorithm(CKM_DES3_CBC_PAD, "DES3/CBC/Pad", IVParameterSpecClasses, true, 8); public static final KeyWrapAlgorithm RSA = new KeyWrapAlgorithm(SEC_OID_PKCS1_RSA_ENCRYPTION, "RSA", (Class) null, false, 0); public static final KeyWrapAlgorithm RSA_OAEP = new KeyWrapAlgorithm(CKM_RSA_PKCS_OAEP, "RSAES-OAEP", OAEPParameterSpec.class, true, 0); public static final KeyWrapAlgorithm PLAINTEXT = new KeyWrapAlgorithm(0, "Plaintext", (Class) null, false, 0); public static final KeyWrapAlgorithm AES_ECB = new KeyWrapAlgorithm(CKM_AES_ECB, "AES/ECB/NoPadding", (Class) null, false, 16); public static final KeyWrapAlgorithm AES_CBC = new KeyWrapAlgorithm(CKM_AES_CBC, "AES/CBC/NoPadding", IVParameterSpecClasses, false, 16); public static final KeyWrapAlgorithm AES_CBC_PAD = new KeyWrapAlgorithm(CKM_AES_CBC_PAD, "AES/CBC/PKCS5Padding", IVParameterSpecClasses, true, 16); public static final KeyWrapAlgorithm RC2_CBC_PAD = new KeyWrapAlgorithm(CKM_RC2_CBC_PAD, "RC2/CBC/PKCS5Padding", RC2ParameterSpec.class, true, 8); /* * Note: AES_KEY_WRAP is not suitable for wrapping private keys; * Use AES_KEY_WRAP_PAD instead * Also note that although it is mapped to CKM_NSS_AES_KEY_WRAP_* * here, down in PK11KeyWrapper.c, logic exists to map to * CKM_AES_KEY_WRAP_* if it is determined to recognize the mechanism */ public static final KeyWrapAlgorithm AES_KEY_WRAP = new KeyWrapAlgorithm(CKM_NSS_AES_KEY_WRAP, "AES KeyWrap/NoPadding", (Class) null, false, 8); public static final KeyWrapAlgorithm AES_KEY_WRAP_PAD = new KeyWrapAlgorithm(CKM_NSS_AES_KEY_WRAP_PAD, "AES KeyWrap/Padding", (Class) null, true, 8); /* * Added to support HSMs. There is no CKM_NSS equivalent, unlike the * above two mechanisms. */ public static final KeyWrapAlgorithm AES_KEY_WRAP_PAD_KWP = new KeyWrapAlgorithm(CKM_AES_KEY_WRAP_KWP, "AES KeyWrap/Wrapped", (Class) null, true, 8); public static final OBJECT_IDENTIFIER AES_KEY_WRAP_PAD_OID = new OBJECT_IDENTIFIER("2.16.840.1.101.3.4.1.8"); public static final OBJECT_IDENTIFIER AES_KEY_WRAP_KWP_OID = new OBJECT_IDENTIFIER("2.16.840.1.101.3.4.1.8"); public static final OBJECT_IDENTIFIER AES_KEY_WRAP_OID = new OBJECT_IDENTIFIER("2.16.840.1.101.3.4.1.5"); public static final OBJECT_IDENTIFIER AES_CBC_PAD_OID = new OBJECT_IDENTIFIER("2.16.840.1.101.3.4.1.2"); public static final OBJECT_IDENTIFIER DES3_CBC_PAD_OID = new OBJECT_IDENTIFIER("1.2.840.113549.3.7"); public static final OBJECT_IDENTIFIER DES_CBC_PAD_OID = new OBJECT_IDENTIFIER("1.3.14.3.2.7"); public static KeyWrapAlgorithm fromOID(String wrapOID) throws NoSuchAlgorithmException { OBJECT_IDENTIFIER oid = new OBJECT_IDENTIFIER(wrapOID); return fromOID(oid); } public static KeyWrapAlgorithm fromOID(OBJECT_IDENTIFIER oid) throws NoSuchAlgorithmException { if (oid.equals(AES_KEY_WRAP_PAD_OID)) return AES_KEY_WRAP_PAD; if (oid.equals(AES_KEY_WRAP_OID)) return AES_KEY_WRAP; if (oid.equals(AES_CBC_PAD_OID)) return AES_CBC_PAD; if (oid.equals(DES3_CBC_PAD_OID)) return DES3_CBC_PAD; if (oid.equals(DES_CBC_PAD_OID)) return DES_CBC_PAD; throw new NoSuchAlgorithmException("Unknown Algorithm for OID: " + oid); } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/KeyWrapper.java000066400000000000000000000121571412550063600242700ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.spec.AlgorithmParameterSpec; import java.security.InvalidAlgorithmParameterException; import java.security.PublicKey; import java.security.InvalidKeyException; public interface KeyWrapper { public void initWrap(SymmetricKey wrappingKey, AlgorithmParameterSpec parameters) throws InvalidKeyException, InvalidAlgorithmParameterException; public void initWrap(PublicKey wrappingKey, AlgorithmParameterSpec parameters) throws InvalidKeyException, InvalidAlgorithmParameterException; /** * For wrapping keys in plaintext. */ public void initWrap() throws InvalidKeyException, InvalidAlgorithmParameterException; public void initUnwrap(SymmetricKey unwrappingKey, AlgorithmParameterSpec parameters) throws InvalidKeyException, InvalidAlgorithmParameterException; public void initUnwrap(PrivateKey unwrappingKey, AlgorithmParameterSpec parameters) throws InvalidKeyException, InvalidAlgorithmParameterException; /** * For plaintext-wrapped keys. */ public void initUnwrap() throws InvalidKeyException, InvalidAlgorithmParameterException; public byte[] wrap(PrivateKey toBeWrapped) throws InvalidKeyException, IllegalStateException, TokenException; public byte[] wrap(SymmetricKey toBeWrapped) throws InvalidKeyException, IllegalStateException, TokenException; /** * Unwraps a private key, creating a permanent private key object. * A permanent private key object resides on a token until it is * explicitly deleted from the token. * * @param publicKey Used to calculate the key identifier that must be stored * with the private key. Must be a RSAPublicKey or a * DSAPublicKey. * @exception InvalidKeyException If the type of the public key does not * match the type of the private key to be unwrapped. */ public PrivateKey unwrapPrivate(byte[] wrapped, PrivateKey.Type type, PublicKey publicKey) throws TokenException, InvalidKeyException, IllegalStateException; /** * Unwraps a private key, creating a temporary private key object. * A temporary * private key is one that does not permanently reside on a token. * As soon as it is garbage-collected, it is gone forever. * * @param publicKey Used to calculate the key identifier that must be stored * with the private key. Must be a RSAPublicKey or a * DSAPublicKey. * @exception InvalidKeyException If the type of the public key does not * match the type of the private key to be unwrapped. */ public PrivateKey unwrapTemporaryPrivate(byte[] wrapped, PrivateKey.Type type, PublicKey publicKey) throws TokenException, InvalidKeyException, IllegalStateException; /** * @param keyLength The expected length of the key in bytes. This is * only used for variable-length keys (RC4) and non-padding * algorithms. Otherwise, it can be set to anything(like 0). * @param usage The operation the key will be used for after it is * unwrapped. You have to specify this so that the key can be properly * marked with the operation it supports. Some PKCS #11 tokens require * that a key be marked for an operation before it can perform that * operation. */ public SymmetricKey unwrapSymmetric(byte[] wrapped, SymmetricKey.Type type, SymmetricKey.Usage usage, int keyLength) throws TokenException, IllegalStateException, InvalidAlgorithmParameterException; /** * Unwraps a key and allows it to be used for all operations. * @param keyLength The expected length of the key in bytes. This is * only used for variable-length keys (RC4) and non-padding * algorithms. Otherwise, it can be set to anything(like 0). */ public SymmetricKey unwrapSymmetric(byte[] wrapped, SymmetricKey.Type type, int keyLength) throws TokenException, IllegalStateException, InvalidAlgorithmParameterException; public SymmetricKey unwrapSymmetricPerm(byte[] wrapped, SymmetricKey.Type type, SymmetricKey.Usage usage, int keyLength) throws TokenException, IllegalStateException, InvalidAlgorithmParameterException; /** * Unwraps a key and allows it to be used for all operations. * @param keyLength The expected length of the key in bytes. This is * only used for variable-length keys (RC4) and non-padding * algorithms. Otherwise, it can be set to anything(like 0). */ public SymmetricKey unwrapSymmetricPerm(byte[] wrapped, SymmetricKey.Type type, int keyLength) throws TokenException, IllegalStateException, InvalidAlgorithmParameterException; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/NoSuchItemOnTokenException.java000066400000000000000000000015651412550063600273730ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; /** * Thrown if a cryptographic item does not exist on the token it is * trying to be used on. */ public class NoSuchItemOnTokenException extends Exception { private static final long serialVersionUID = 1L; public NoSuchItemOnTokenException() {} public NoSuchItemOnTokenException(String mesg) { super(mesg); } public NoSuchItemOnTokenException(String mesg, Throwable cause) { super(mesg, cause); } public NoSuchItemOnTokenException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(mesg, cause, enableSuppression, writableStackTrace); } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/NoSuchPaddingException.java000066400000000000000000000007021412550063600265350ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; /** * This class is a stub for javax.crypto.NoSuchPaddingException until we * move to JDK 1.2. */ public class NoSuchPaddingException extends Exception { private static final long serialVersionUID = 1L; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/ObjectNotFoundException.java000066400000000000000000000014711412550063600267360ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; /** * This exception is thrown whenever something isn't implemented. */ public class ObjectNotFoundException extends Exception { private static final long serialVersionUID = 1L; public ObjectNotFoundException() { super(); } public ObjectNotFoundException(String mesg) { super(mesg); } public ObjectNotFoundException(String mesg, Throwable cause) { super(mesg, cause); } public ObjectNotFoundException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(mesg, cause, enableSuppression, writableStackTrace); } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/PBEAlgorithm.java000066400000000000000000000125061412550063600244520ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; /** * Algorithms that can be used for generating symmetric keys from passwords. */ public class PBEAlgorithm extends KeyGenAlgorithm { private EncryptionAlgorithm encAlg; private int saltLength; protected PBEAlgorithm(int oidTag, String name, int validStrength, OBJECT_IDENTIFIER oid, EncryptionAlgorithm encAlg, int saltLength) { super(oidTag, name, new FixedKeyStrengthValidator(validStrength), oid, PBEKeyGenParams.class); this.encAlg = encAlg; this.saltLength = saltLength; } /** * Returns the EncryptionAlgorithm that should be used with keys * generated with this PBEAlgorithm. For example, * PBE_MD2_DES_CBC.getEncryptionAlg() returns * EncryptionAlgorithm.DES_CBC. */ public EncryptionAlgorithm getEncryptionAlg() { return encAlg; } /** * Returns the number of bytes of salt that should be supplied when * generating keys with this algorithm. * *

PKCS #5 algorithms require exactly 8 bytes of salt. PKCS #12 * algorithms take * a variable length, but recommend that the salt length be at least * as long as the output of the hash function. For SHA-1, the output * length is 20 bytes. */ public int getSaltLength() { return saltLength; } /////////////////////////////////////////////////////////////////////// // OIDs /////////////////////////////////////////////////////////////////////// private static final OBJECT_IDENTIFIER PKCS5 = OBJECT_IDENTIFIER.PKCS5; private static final OBJECT_IDENTIFIER PKCS12_PBE = OBJECT_IDENTIFIER.PKCS12.subBranch(1); /////////////////////////////////////////////////////////////////////// // OID mapping /////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// // PKCS 5 v2 public static final PBEAlgorithm PBE_PKCS5_PBKDF2 = new PBEAlgorithm( SEC_OID_PKCS5_PBKDF2, "PBKDF2", 128, PKCS5.subBranch(12), EncryptionAlgorithm.AES_128_CBC, 8 ); ////////////////////////////////////////////////////////////// // PKCS 5 v2 public static final PBEAlgorithm PBE_PKCS5_PBES2 = new PBEAlgorithm( SEC_OID_PKCS5_PBES2, "PBES2", 128, PKCS5.subBranch(13), EncryptionAlgorithm.AES_128_CBC, 8 ); ////////////////////////////////////////////////////////////// // PKCS 5 v2 public static final PBEAlgorithm PBE_PKCS5_PBMAC1 = new PBEAlgorithm( SEC_OID_PKCS5_PBMAC1, "PBMAC1", 128, PKCS5.subBranch(14), EncryptionAlgorithm.AES_128_CBC, 8 ); ////////////////////////////////////////////////////////////// public static final PBEAlgorithm PBE_MD2_DES_CBC = new PBEAlgorithm( SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC, "PBE/MD2/DES/CBC", 56, PKCS5.subBranch(1), EncryptionAlgorithm.DES_CBC, 8 ); ////////////////////////////////////////////////////////////// public static final PBEAlgorithm PBE_MD5_DES_CBC = new PBEAlgorithm( SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC, "PBE/MD5/DES/CBC", 56, PKCS5.subBranch(3), EncryptionAlgorithm.DES_CBC, 8 ); ////////////////////////////////////////////////////////////// public static final PBEAlgorithm PBE_SHA1_DES_CBC = new PBEAlgorithm( SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC, "PBE/SHA1/DES/CBC", 56, PKCS5.subBranch(10), EncryptionAlgorithm.DES_CBC, 8 ); ////////////////////////////////////////////////////////////// public static final PBEAlgorithm PBE_SHA1_RC4_128 = new PBEAlgorithm( SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4, "PBE/SHA1/RC4-128", 128, PKCS12_PBE.subBranch(1), EncryptionAlgorithm.RC4, 20 ); ////////////////////////////////////////////////////////////// public static final PBEAlgorithm PBE_SHA1_RC4_40 = new PBEAlgorithm( SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4, "PBE/SHA1/RC4-40", 40, PKCS12_PBE.subBranch(2), EncryptionAlgorithm.RC4, 20 ); ////////////////////////////////////////////////////////////// public static final PBEAlgorithm PBE_SHA1_DES3_CBC = new PBEAlgorithm( SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC, "PBE/SHA1/DES3/CBC", 168, PKCS12_PBE.subBranch(3), EncryptionAlgorithm.DES3_CBC, 20 ); ////////////////////////////////////////////////////////////// public static final PBEAlgorithm PBE_SHA1_RC2_128_CBC = new PBEAlgorithm( SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC, "PBE/SHA1/RC2-128", 128, PKCS12_PBE.subBranch(5), EncryptionAlgorithm.RC2_CBC, 20 ); ////////////////////////////////////////////////////////////// public static final PBEAlgorithm PBE_SHA1_RC2_40_CBC = new PBEAlgorithm( SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC, "PBE/SHA1/RC2-40", 40, PKCS12_PBE.subBranch(6), EncryptionAlgorithm.RC2_CBC, 20 ); } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/PBEKeyGenParams.java000066400000000000000000000107571412550063600250600ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.KeySpec; import org.mozilla.jss.util.Password; public class PBEKeyGenParams implements AlgorithmParameterSpec, KeySpec { private Password pass; private byte[] salt; private int iterations; private EncryptionAlgorithm encryptionAlgorithm = EncryptionAlgorithm.DES3_CBC; static private final int DEFAULT_SALT_LENGTH = 8; static private final int DEFAULT_ITERATIONS = 1; /** * Creates PBE parameters. * * @param pass The password. It will be cloned, so the * caller is still responsible for clearing it. It must not be null. * @param salt The salt for the PBE algorithm. Will not be cloned. * Must not be null. It is the responsibility of the caller to * use the right salt length for the algorithm. Most algorithms * use 8 bytes of salt. * @param iterations The iteration count for the PBE algorithm. */ public PBEKeyGenParams(Password pass, byte[] salt, int iterations) { if (pass == null || salt == null) { throw new NullPointerException(); } this.pass = (Password) pass.clone(); this.salt = salt; this.iterations = iterations; } /** * Creates PBE parameters using default encryption algorithm * (DES3_EDE3_CBC). * * @param pass The password. It will be cloned, so the * caller is still responsible for clearing it. It must not be null. * @param salt The salt for the PBE algorithm. Will not be cloned. * Must not be null. It is the responsibility of the caller to * use the right salt length for the algorithm. Most algorithms * use 8 bytes of salt. * @param iterations The iteration count for the PBE algorithm. */ public PBEKeyGenParams(char[] pass, byte[] salt, int iterations) { if (pass == null || salt == null) { throw new NullPointerException(); } this.pass = new Password(pass.clone()); this.salt = salt; this.iterations = iterations; } /** * Creates PBE parameters using default encryption algorithm * (DES3_EDE3_CBC). * * @param pass The password. It will be cloned, so the * caller is still responsible for clearing it. It must not be null. * @param salt The salt for the PBE algorithm. Will not be cloned. * Must not be null. It is the responsibility of the caller to * use the right salt length for the algorithm. Most algorithms * use 8 bytes of salt. * @param iterations The iteration count for the PBE algorithm. * @param encAlg The encryption algorithm. This is used with SOME * PBE algorithms for determining the KDF output length. */ public PBEKeyGenParams( char[] pass, byte[] salt, int iterations, EncryptionAlgorithm encAlg) { if (pass == null || salt == null) { throw new NullPointerException(); } this.pass = new Password(pass.clone()); this.salt = salt; this.iterations = iterations; if (encAlg != null) this.encryptionAlgorithm = encAlg; } /** * Returns a reference to the password, not a copy. */ public Password getPassword() { return pass; } /** * Returns a reference to the salt. */ public byte[] getSalt() { return salt; } /** * Returns the iteration count. */ public int getIterations() { return iterations; } /** * The encryption algorithm is used with SOME PBE algorithms for * determining the KDF output length. */ public EncryptionAlgorithm getEncryptionAlgorithm() { return encryptionAlgorithm; } /** * Clears the password. This should be called when this object is no * longer needed so the password is not left around in memory. */ public void clear() { pass.clear(); } /** * @deprecated finalize() in Object has been deprecated */ @Override @Deprecated protected void finalize() throws Throwable { pass.clear(); } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/PKCS11Algorithm.java000066400000000000000000000104071412550063600247440ustar00rootroot00000000000000package org.mozilla.jss.crypto; import org.mozilla.jss.pkcs11.PKCS11Constants; public enum PKCS11Algorithm { CKM_AES_CBC (Algorithm.CKM_AES_CBC, PKCS11Constants.CKM_AES_CBC), CKM_AES_CBC_PAD (Algorithm.CKM_AES_CBC_PAD, PKCS11Constants.CKM_AES_CBC_PAD), CKM_AES_ECB (Algorithm.CKM_AES_ECB, PKCS11Constants.CKM_AES_ECB), CKM_AES_KEY_GEN (Algorithm.CKM_AES_KEY_GEN, PKCS11Constants.CKM_AES_KEY_GEN), CKM_DES3_CBC_PAD (Algorithm.CKM_DES3_CBC_PAD, PKCS11Constants.CKM_DES3_CBC_PAD), CKM_DES3_ECB (Algorithm.CKM_DES3_ECB, PKCS11Constants.CKM_DES3_ECB), CKM_DES3_KEY_GEN (Algorithm.CKM_DES3_KEY_GEN, PKCS11Constants.CKM_DES3_KEY_GEN), CKM_DES_CBC_PAD (Algorithm.CKM_DES_CBC_PAD, PKCS11Constants.CKM_DES_CBC_PAD), CKM_DES_KEY_GEN (Algorithm.CKM_DES_KEY_GEN, PKCS11Constants.CKM_DES_KEY_GEN), CKM_DSA_KEY_PAIR_GEN (Algorithm.CKM_DSA_KEY_PAIR_GEN, PKCS11Constants.CKM_DSA_KEY_PAIR_GEN), CKM_EC_KEY_PAIR_GEN (Algorithm.CKM_EC_KEY_PAIR_GEN, PKCS11Constants.CKM_EC_KEY_PAIR_GEN), CKM_NSS_AES_KEY_WRAP (Algorithm.CKM_NSS_AES_KEY_WRAP, PKCS11Constants.CKM_NSS_AES_KEY_WRAP), CKM_NSS_AES_KEY_WRAP_PAD (Algorithm.CKM_NSS_AES_KEY_WRAP_PAD, PKCS11Constants.CKM_NSS_AES_KEY_WRAP_PAD), CKM_PBA_SHA1_WITH_SHA1_HMAC (Algorithm.CKM_PBA_SHA1_WITH_SHA1_HMAC, PKCS11Constants.CKM_PBA_SHA1_WITH_SHA1_HMAC), CKM_RC2_CBC_PAD (Algorithm.CKM_RC2_CBC_PAD, PKCS11Constants.CKM_RC2_CBC_PAD), CKM_RC2_KEY_GEN (Algorithm.CKM_RC2_KEY_GEN, PKCS11Constants.CKM_RC2_KEY_GEN), CKM_RC4_KEY_GEN (Algorithm.CKM_RC4_KEY_GEN, PKCS11Constants.CKM_RC4_KEY_GEN), CKM_RSA_PKCS_KEY_PAIR_GEN (Algorithm.CKM_RSA_PKCS_KEY_PAIR_GEN, PKCS11Constants.CKM_RSA_PKCS_KEY_PAIR_GEN), CKM_SHA_1_HMAC (Algorithm.CKM_SHA_1_HMAC, PKCS11Constants.CKM_SHA_1_HMAC), CKM_SHA_256_HMAC (Algorithm.CKM_SHA256_HMAC, PKCS11Constants.CKM_SHA256_HMAC), CKM_SHA_384_HMAC (Algorithm.CKM_SHA384_HMAC, PKCS11Constants.CKM_SHA384_HMAC), CKM_SHA_512_HMAC (Algorithm.CKM_SHA512_HMAC, PKCS11Constants.CKM_SHA512_HMAC), CKM_AES_CMAC (Algorithm.CKM_AES_CMAC, PKCS11Constants.CKM_AES_CMAC), CKM_SP800_108_COUNTER_KDF (Algorithm.CKM_SP800_108_COUNTER_KDF, PKCS11Constants.CKM_SP800_108_COUNTER_KDF), CKM_SP800_108_FEEDBACK_KDF (Algorithm.CKM_SP800_108_FEEDBACK_KDF, PKCS11Constants.CKM_SP800_108_FEEDBACK_KDF), CKM_SP800_108_DOUBLE_PIPELINE_KDF (Algorithm.CKM_SP800_108_DOUBLE_PIPELINE_KDF, PKCS11Constants.CKM_SP800_108_DOUBLE_PIPELINE_KDF), CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA (Algorithm.CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA, PKCS11Constants.CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA), CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA (Algorithm.CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA, PKCS11Constants.CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA), CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA (Algorithm.CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA, PKCS11Constants.CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA), CKM_MD2(Algorithm.SEC_OID_MD2, PKCS11Constants.CKM_MD2), CKM_MD5(Algorithm.SEC_OID_MD5, PKCS11Constants.CKM_MD5), CKM_SHA_1(Algorithm.SEC_OID_SHA1, PKCS11Constants.CKM_SHA_1), CKM_SHA256(Algorithm.SEC_OID_SHA256, PKCS11Constants.CKM_SHA256), CKM_SHA384(Algorithm.SEC_OID_SHA384, PKCS11Constants.CKM_SHA384), CKM_SHA512(Algorithm.SEC_OID_SHA512, PKCS11Constants.CKM_SHA512); // Value from Algorithm's constant -- this is an index into Algorithm's // table. private int alg_index; // Value from PKCS11Constants -- this is a constant defined in PKCS #11. private long pk11_value; private PKCS11Algorithm(int alg_index, long pk11_value) { this.alg_index = alg_index; this.pk11_value = pk11_value; } public int getIndex() { return alg_index; } public long getValue() { return pk11_value; } public static PKCS11Algorithm valueOfIndex(int index) { for (PKCS11Algorithm alg : PKCS11Algorithm.values()) { if (alg.alg_index == index) { return alg; } } return null; } public static PKCS11Algorithm valueOfConstant(long constant) { for (PKCS11Algorithm alg : PKCS11Algorithm.values()) { if (alg.pk11_value == constant) { return alg; } } return null; } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/PQGParamGenException.java000066400000000000000000000013261412550063600261140ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; public class PQGParamGenException extends Exception { private static final long serialVersionUID = 1L; public PQGParamGenException() {} public PQGParamGenException(String mesg) { super(mesg); } public PQGParamGenException(String mesg, Throwable cause) { super(mesg, cause); } public PQGParamGenException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(mesg, cause, enableSuppression, writableStackTrace); } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/PQGParams.c000066400000000000000000000243461412550063600232760ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "_jni/org_mozilla_jss_crypto_PQGParams.h" #include #include #include #include #include /* for PQGParams */ #include #include #include #include #include static jobject generate(JNIEnv *env, jclass PQGParamsClass, jint keySize, jint seedBytes); /********************************************************************** * P Q G P a r a m s . g e n e r a t e ( keysize ) * */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_crypto_PQGParams_generateNative__I (JNIEnv *env, jclass PQGParamsClass, jint keySize) { return generate(env, PQGParamsClass, keySize, 0); } /********************************************************************** * P Q G P a r a m s . g e n e r a t e ( keysize, seedBytes ) * */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_crypto_PQGParams_generateNative__II (JNIEnv *env, jclass PQGParamsClass, jint keySize, jint seedBytes) { if(seedBytes < 20 || seedBytes > 255) { JSS_throwMsg(env, INVALID_PARAMETER_EXCEPTION, "Number of bytes in seed must be in range [20,255]"); return NULL; } return generate(env, PQGParamsClass, keySize, seedBytes); } #define ZERO_SECITEM(item) (item).data=NULL; (item).len=0; /********************************************************************** * * g e n e r a t e * * INPUTS * env * The JNI environment. * this * Reference to a Java PQGGenerator object. * keySize * The size of the key, which is actually the size of P in bits. * seedBytes * The length of the seed in bytes, or 0 to let the algorithm * figure it out. * RETURNS * A new PQGParams object. */ static jobject generate(JNIEnv *env, jclass PQGParamsClass, jint keySize, jint seedBytes) { int keySizeIndex; jobject newObject = NULL; SECStatus status; PQGParams *pParams=NULL; PQGVerify *pVfy=NULL; jbyteArray bytes; jclass BigIntegerClass; jmethodID BigIntegerConstructor; jmethodID PQGParamsConstructor; /*----PQG parameters and friends----*/ SECItem P; /* prime */ SECItem Q; /* subPrime */ SECItem G; /* base */ SECItem H; SECItem seed; unsigned int counter; /*----Java versions of the PQG parameters----*/ jobject jP; jobject jQ; jobject jG; jobject jH; jint jcounter; jobject jSeed; /* basic argument validation */ PR_ASSERT(env!=NULL && PQGParamsClass!=NULL); /* clear the SECItems so we can free them indiscriminately at the end */ ZERO_SECITEM(P); ZERO_SECITEM(Q); ZERO_SECITEM(G); ZERO_SECITEM(H); ZERO_SECITEM(seed); /*********************************************************************** * PK11_PQG_ParamGen doesn't take a key size, it takes an index that * points to a valid key size. */ keySizeIndex = PQG_PBITS_TO_INDEX(keySize); if(keySizeIndex == -1 || keySize<512 || keySize>1024) { JSS_throwMsg(env, INVALID_PARAMETER_EXCEPTION, "DSA key size must be a multiple of 64 between 512 " "and 1024, inclusive"); goto finish; } /*********************************************************************** * Do the actual parameter generation. */ if(seedBytes == 0) { status = PK11_PQG_ParamGen(keySizeIndex, &pParams, &pVfy); } else { status = PK11_PQG_ParamGenSeedLen(keySizeIndex, seedBytes, &pParams, &pVfy); } if(status != SECSuccess) { JSS_throw(env, PQG_PARAM_GEN_EXCEPTION); goto finish; } /********************************************************************** * NOTE: the new PQG parameters will be verified at the Java level. */ /********************************************************************** * Get ready for the BigIntegers */ BigIntegerClass = (*env)->FindClass(env, BIG_INTEGER_CLASS_NAME); if(BigIntegerClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } BigIntegerConstructor = (*env)->GetMethodID(env, BigIntegerClass, BIG_INTEGER_CONSTRUCTOR_NAME, BIG_INTEGER_CONSTRUCTOR_SIG); if(BigIntegerConstructor == NULL) { ASSERT_OUTOFMEM(env); goto finish; } /*********************************************************************** * Convert the parameters to Java types. */ if( PK11_PQG_GetPrimeFromParams( pParams, &P) || PK11_PQG_GetSubPrimeFromParams( pParams, &Q) || PK11_PQG_GetBaseFromParams( pParams, &G) || PK11_PQG_GetHFromVerify( pVfy, &H) || PK11_PQG_GetSeedFromVerify( pVfy, &seed) ) { JSS_throw(env, PQG_PARAM_GEN_EXCEPTION); goto finish; } counter = PK11_PQG_GetCounterFromVerify(pVfy); /* * construct P */ bytes = JSS_OctetStringToByteArray(env, &P); if(bytes==NULL) { ASSERT_OUTOFMEM(env); goto finish; } jP = (*env)->NewObject(env, BigIntegerClass, BigIntegerConstructor, bytes); if(jP==NULL) { ASSERT_OUTOFMEM(env); goto finish; } /* * construct Q */ bytes = JSS_OctetStringToByteArray(env, &Q); if(bytes==NULL) { ASSERT_OUTOFMEM(env); goto finish; } jQ = (*env)->NewObject(env, BigIntegerClass, BigIntegerConstructor, bytes); if(jQ==NULL) { ASSERT_OUTOFMEM(env); goto finish; } /* * construct G */ bytes = JSS_OctetStringToByteArray(env, &G); if(bytes==NULL) { ASSERT_OUTOFMEM(env); goto finish; } jG = (*env)->NewObject(env, BigIntegerClass, BigIntegerConstructor, bytes); if(jG==NULL) { ASSERT_OUTOFMEM(env); goto finish; } /* * construct seed */ bytes = JSS_OctetStringToByteArray(env, &seed); if(bytes==NULL) { ASSERT_OUTOFMEM(env); goto finish; } jSeed = (*env)->NewObject(env, BigIntegerClass, BigIntegerConstructor, bytes); if(jSeed==NULL) { ASSERT_OUTOFMEM(env); goto finish; } /* * construct H */ bytes = JSS_OctetStringToByteArray(env, &H); if(bytes==NULL) { ASSERT_OUTOFMEM(env); goto finish; } jH = (*env)->NewObject(env, BigIntegerClass, BigIntegerConstructor, bytes); if(jH==NULL) { ASSERT_OUTOFMEM(env); goto finish; } /* * construct counter */ jcounter = counter; /********************************************************************** * Construct the PQGParams object */ PQGParamsConstructor = (*env)->GetMethodID( env, PQGParamsClass, PQG_PARAMS_CONSTRUCTOR_NAME, PQG_PARAMS_CONSTRUCTOR_SIG); if(PQGParamsConstructor==NULL) { ASSERT_OUTOFMEM(env); goto finish; } newObject = (*env)->NewObject( env, PQGParamsClass, PQGParamsConstructor, jP, jQ, jG, jSeed, jcounter, jH); finish: if(pParams!=NULL) { PK11_PQG_DestroyParams(pParams); } if(pVfy!=NULL) { PK11_PQG_DestroyVerify(pVfy); } SECITEM_FreeItem(&P, PR_FALSE /*don't free P itself*/); SECITEM_FreeItem(&Q, PR_FALSE); SECITEM_FreeItem(&G, PR_FALSE); SECITEM_FreeItem(&H, PR_FALSE); SECITEM_FreeItem(&seed, PR_FALSE); return newObject; } /********************************************************************** * * P Q G P a r a m s . p a r a m s A r e V a l i d * */ JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_crypto_PQGParams_paramsAreValidNative (JNIEnv *env, jobject this, jbyteArray jP, jbyteArray jQ, jbyteArray jG, jbyteArray jSeed, jint jCounter, jbyteArray jH) { jboolean valid=JNI_FALSE; PQGParams *pParams=NULL; PQGVerify *pVfy=NULL; SECStatus verifyResult; /*---PQG and verification params in C---*/ SECItem P; SECItem Q; SECItem G; SECItem seed; SECItem H; unsigned int counter; PR_ASSERT(env!=NULL && this!=NULL); /* clear the SECItems so we can free them indiscriminately later */ ZERO_SECITEM(P); ZERO_SECITEM(Q); ZERO_SECITEM(G); ZERO_SECITEM(seed); ZERO_SECITEM(H); /********************************************************************** * Extract the Java parameters */ if( JSS_ByteArrayToOctetString(env, jP, &P) || JSS_ByteArrayToOctetString(env, jQ, &Q) || JSS_ByteArrayToOctetString(env, jG, &G) || JSS_ByteArrayToOctetString(env, jSeed, &seed) || JSS_ByteArrayToOctetString(env, jH, &H) ) { goto finish; } counter = jCounter; /*********************************************************************** * Construct PQGParams and PQGVerify structures. */ pParams = PK11_PQG_NewParams(&P, &Q, &G); pVfy = PK11_PQG_NewVerify(counter, &seed, &H); if(pParams==NULL || pVfy==NULL) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } /*********************************************************************** * Perform the verification. */ if( PK11_PQG_VerifyParams(pParams, pVfy, &verifyResult) != SECSuccess) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } if(verifyResult == SECSuccess) { valid = JNI_TRUE; } finish: SECITEM_FreeItem(&P, PR_FALSE /*don't free P itself*/); SECITEM_FreeItem(&Q, PR_FALSE); SECITEM_FreeItem(&G, PR_FALSE); SECITEM_FreeItem(&seed, PR_FALSE); SECITEM_FreeItem(&H, PR_FALSE); PK11_PQG_DestroyParams(pParams); PK11_PQG_DestroyVerify(pVfy); return valid; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/PQGParams.java000066400000000000000000000176621412550063600240000ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.math.BigInteger; import java.security.spec.DSAParameterSpec; /** * PQG parameters for DSA key generation, along with the seed, counter, * and H values for verification. *

This class has two main purposes: * generating PQG parameters and verifying PQG parameters. To generate * PQG parameters, call one of the static generate methods. * They will return a new set of PQG parameters. To verify existing PQG * parameters, create a new PQGParams object with the * constructor and call paramsAreValid on the object. * *

It is necessary to call CryptoManager.initialize before * using this class. * */ public class PQGParams extends DSAParameterSpec { /** * Creates a PQGParams object from a set of pre-computed DSA * parameters. * * @param P The DSA prime parameter. * @param Q The DSA sub-prime parameter. * @param G The DSA base parameter. * @param seed The Seed used to calculate P, Q, and G. * @param counter The Counter (C) used to calculate P, Q, and G. * @param H The H value used to generate P, Q, and G. */ public PQGParams(BigInteger P, BigInteger Q, BigInteger G, BigInteger seed, int counter, BigInteger H) { super(P, Q, G); this.seed = seed; this.counter = counter; this.H = H; } /** * Generates P, Q, and G parameters for DSA key generation. Also * provides the seed, counter, and H values for verification of the * P, Q, and G. The parameters are generated and then verified * before being returned. The length of the Seed will equal the * length of P. * * It is necessary to call one of the * CryptoManager.initialize functions before calling * this method. * * @param keySize The size of P in bits. Keys generated by these P, * Q, and G values will have this length. Valid key sizes * are multiples of 64 in the closed interval [512,1024]. * This also dictates the length of H and Seed. * @return A new set of P, Q, and G parameters, along with the Seed, * Counter, and H values used to generate them. * @exception java.security.InvalidParameterException If the keySize * is outside the bounds described by the DSA key pair * generation algorithm. * @exception org.mozilla.jss.crypto.PQGParamGenException If an error * occurs during the generation process. * @see org.mozilla.jss.CryptoManager#initialize */ public static PQGParams generate(int keySize) throws java.security.InvalidParameterException, PQGParamGenException { PQGParams pqg = generateNative(keySize); if( ! pqg.paramsAreValid() ) { throw new PQGParamGenException( "Generated parameters did not verify correctly"); } return pqg; } /** * Does the actual work of generation, but does not verify. */ private static native PQGParams generateNative(int keySize) throws java.security.InvalidParameterException, PQGParamGenException; /** * Generates P, Q, and G parameters for DSA key generation. Also * provides the seed, counter, and H values for verification of the * P, Q, and G. The parameters are generated and then verified * before being returned. * * It is necessary to call one of the * CryptoManager.initialize functions before calling * this method. * * @param keySize The size of P in bits. Keys generated by these P, * Q, and G values will have this length. Valid key sizes * are multiples of 64 in the closed interval [512,1024]. * This also dictates the length of H. * @param seedBytes The number of bytes in the Seed value used to * generate P, Q, and G. seedBytes must be * from the closed interval [20,255]. * @return A new set of P, Q, and G parameters, along with the Seed, * Counter, and H values used to generate them. * @exception java.security.InvalidParameterException If the keySize * or number of seed bytes is outside the bounds described by the * DSA key pair generation algorithm. * @exception org.mozilla.jss.crypto.PQGParamGenException If an error * occurs during the generation process. * @see org.mozilla.jss.CryptoManager#initialize */ public static PQGParams generate(int keySize, int seedBytes) throws java.security.InvalidParameterException, PQGParamGenException { PQGParams pqg = generateNative(keySize, seedBytes); if( ! pqg.paramsAreValid() ) { throw new PQGParamGenException( "Generated parameters did not verify correctly"); } return pqg; } /** * Does the actual work of generation, but does not verify. */ private static native PQGParams generateNative(int keySize, int seedBytes) throws java.security.InvalidParameterException, PQGParamGenException; /** * Produces an unsigned byte-array representation of a BigInteger. * *

BigInteger adds an extra sign bit to the beginning of its byte * array representation. In some cases this will cause the size * of the byte array to increase, which may be unacceptable for some * applications. This function returns a minimal byte array representing * the BigInteger without extra sign bits. * * @return An unsigned, big-endian byte array representation * of a BigInteger. */ public static byte[] BigIntegerToUnsignedByteArray(BigInteger big) { byte[] ret; // big must not be negative assert(big.signum() != -1); // bitLength is the size of the data without the sign bit. If // it exactly fills an integral number of bytes, that means a whole // new byte will have to be added to accomodate the sign bit. In // this case we need to remove the first byte. if(big.bitLength() % 8 == 0) { byte[] array = big.toByteArray(); // The first byte should just be sign bits assert( array[0] == 0 ); ret = new byte[array.length-1]; System.arraycopy(array, 1, ret, 0, ret.length); } else { ret = big.toByteArray(); } return ret; } /** * Verifies the PQG parameters using the seed, counter, and H values. * @return true if the parameters verified correctly, false if they * did not verify. */ public boolean paramsAreValid() { return paramsAreValidNative(BigIntegerToUnsignedByteArray( getP() ), BigIntegerToUnsignedByteArray( getQ() ), BigIntegerToUnsignedByteArray( getG() ), BigIntegerToUnsignedByteArray( seed ), counter, BigIntegerToUnsignedByteArray( H )); } private native boolean paramsAreValidNative(byte[] P, byte[] Q, byte[]G, byte[] seed, int counter, byte[] H); /** * @return The Seed used to generate P, Q, and G. */ public BigInteger getSeed() { return seed; } /** * @return The Counter (C) used to generate P, Q, and G. */ public int getCounter() { return counter; } /** * @return The H value used to generate P, Q, and G. */ public BigInteger getH() { return H; } private BigInteger seed; private int counter; private BigInteger H; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/Policy.c000066400000000000000000000023051412550063600227310ustar00rootroot00000000000000#include "_jni/org_mozilla_jss_crypto_Policy.h" #include #include #include jint nearest_power_of_two(jint value) { for (jint exponent = 8; exponent < 20; exponent++) { if ((1 << exponent) >= value) { return 1 << exponent; } } return value; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_crypto_Policy_getRSAMinimumKeySize(JNIEnv *env, jclass clazz) { PRInt32 value = 0; SECStatus ret = NSS_OptionGet(NSS_RSA_MIN_KEY_SIZE, &value); if (ret != SECSuccess) { PR_ASSERT(PR_FALSE); } return nearest_power_of_two(value); } JNIEXPORT jint JNICALL Java_org_mozilla_jss_crypto_Policy_getDHMinimumKeySize(JNIEnv *env, jclass clazz) { PRInt32 value = 0; SECStatus ret = NSS_OptionGet(NSS_DH_MIN_KEY_SIZE, &value); if (ret != SECSuccess) { PR_ASSERT(PR_FALSE); } return nearest_power_of_two(value); } JNIEXPORT jint JNICALL Java_org_mozilla_jss_crypto_Policy_getDSAMinimumKeySize(JNIEnv *env, jclass clazz) { PRInt32 value = 0; SECStatus ret = NSS_OptionGet(NSS_DSA_MIN_KEY_SIZE, &value); if (ret != SECSuccess) { PR_ASSERT(PR_FALSE); } return nearest_power_of_two(value); } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/Policy.java000066400000000000000000000045101412550063600234300ustar00rootroot00000000000000package org.mozilla.jss.crypto; import java.math.BigInteger; import org.mozilla.jss.ssl.SSLProtocolVariant; import org.mozilla.jss.ssl.SSLSocket; import org.mozilla.jss.ssl.SSLVersion; import org.mozilla.jss.ssl.SSLVersionRange; /** * This class helps JSS callers align with local system cryptographic policy. * * In the event of a policy violation, applications can override policy by * writing to the desired variable. * * Refer to SSLCipher.isSupported() for whether or not a given TLS cipher * suite is allowed by local policy. */ public class Policy { /** * Whether or not this JSS instance is enforcing local crypto-policy, * with respect to key sizes. * * Defaults to false; this lets applications use whatever key sizes are * supported by NSS, at the risk of performing non-compliant operations. * Set to true to enable enforcement, where it exists. */ public static boolean ENFORCING_KEY_SIZES = false; /** * Minimum RSA key length in bits permitted by local policy. */ public static int RSA_MINIMUM_KEY_SIZE = getRSAMinimumKeySize(); /** * Minimum RSA public exponent allowed by JSS. */ public static BigInteger RSA_MINIMUM_PUBLIC_EXPONENT = BigInteger.valueOf(65537); /** * Minimum DH key length in bits permitted by local policy. */ public static int DH_MINIMUM_KEY_SIZE = getDHMinimumKeySize(); /** * Minimum DSA key length in bits permitted by local policy. */ public static int DSA_MINIMUM_KEY_SIZE = getDSAMinimumKeySize(); public static SSLVersionRange TLS_VERSION_RANGE = getTLSVersionRange(); public static SSLVersion TLS_MINIMUM_VERSION = TLS_VERSION_RANGE.getMinVersion(); public static SSLVersion TLS_MAXIMUM_VERSION = TLS_VERSION_RANGE.getMaxVersion(); private static SSLVersionRange getTLSVersionRange() { SSLVersionRange range = new SSLVersionRange(SSLVersion.minSupported(), SSLVersion.maxSupported()); try { return SSLSocket.boundSSLVersionRange(SSLProtocolVariant.STREAM, range); } catch (Exception e) { return range; } } private static native int getRSAMinimumKeySize(); private static native int getDHMinimumKeySize(); private static native int getDSAMinimumKeySize(); } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/PrivateKey.java000066400000000000000000000070531412550063600242610ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.NoSuchAlgorithmException; import java.util.Hashtable; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; /** * Private Keys used by JSS. All the private keys handled by JSS are * of this type, which is a subtype of java.security.PrivateKey. */ public interface PrivateKey extends java.security.PrivateKey { public static final Type RSA = Type.RSA; public static final Type DSA = Type.DSA; public static final Type EC = Type.EC; public static final Type DiffieHellman = Type.DiffieHellman; /** * Returns the type (RSA or DSA) of this private key. */ public Type getType(); /** * Returns the unique ID of this key. Unique IDs can be used to match * certificates to keys. * * @see org.mozilla.jss.crypto.TokenCertificate#getUniqueID */ public byte[] getUniqueID() throws TokenException; /** * Returns the size, in bits, of the modulus of an RSA key. * Returns -1 for other types of keys. */ public int getStrength(); /** * Returns the CryptoToken that owns this private key. Cryptographic * operations with this key may only be performed on the token that * owns the key. */ public CryptoToken getOwningToken(); public static final class Type { private OBJECT_IDENTIFIER oid; private String name; private int pkcs11Type; private Type() { } private Type(OBJECT_IDENTIFIER oid, String name, int pkcs11Type) { this.oid = oid; this.name = name; Object old = oidMap.put(oid, this); this.pkcs11Type = pkcs11Type; assert (old == null); } private static Hashtable oidMap = new Hashtable<>(); public static Type fromOID(OBJECT_IDENTIFIER oid) throws NoSuchAlgorithmException { Object obj = oidMap.get(oid); if (obj == null) { throw new NoSuchAlgorithmException(); } return (Type) obj; } /** * Returns a string representation of the algorithm, such as * "RSA", "DSA", or "EC". */ @Override public String toString() { return name; } public OBJECT_IDENTIFIER toOID() { return oid; } public int getPKCS11Type() { return pkcs11Type; } // OID for DiffieHellman, from RFC 2459 7.3.2. public static OBJECT_IDENTIFIER DH_OID = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 10046, 2, 1 }); // From PKCS #11 private static int CKK_RSA = 0x0; private static int CKK_DSA = 0x1; private static int CKK_DH = 0x2; private static int CKK_EC = 0x3; private static int CKK_X9_42_DH = 0x4; private static int CKK_KEA = 0x5; public static final Type RSA = new Type( OBJECT_IDENTIFIER.PKCS1.subBranch(1), "RSA", CKK_RSA); public static final Type DSA = new Type( Algorithm.ANSI_X9_ALGORITHM.subBranch(1), "DSA", CKK_DSA); public static final Type EC = new Type( Algorithm.ANSI_X962_OID.subBranch(2).subBranch(1), "EC", CKK_EC); public static final Type DiffieHellman = new Type( DH_OID, "DiffieHellman", CKK_DH); } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/RSAParameterSpec.java000066400000000000000000000017231412550063600252750ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.spec.RSAKeyGenParameterSpec; import java.math.BigInteger; /** * This class specifies the parameters used for generating an RSA key pair. */ public class RSAParameterSpec extends RSAKeyGenParameterSpec { /** * Creates a new RSAParameterSpec with the specified parameter values. * @param keySize The size of the modulus in bits. * @param publicExponent The public exponent e. Common values * are 3, 17, and 65537. 65537 is recommended. */ public RSAParameterSpec(int keySize, BigInteger publicExponent) { super(keySize, publicExponent); } /** * Returns the size of the modulus in bits. */ public int getKeySize() { return getKeysize(); } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/SecretDecoderRing.c000066400000000000000000000037141412550063600250320ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "_jni/org_mozilla_jss_crypto_SecretDecoderRing.h" #include #include #include #include #include typedef enum {SDR_ENCRYPT, SDR_DECRYPT} SDROp; static jbyteArray doSDR(JNIEnv *env, jobject this, jbyteArray inputBA, SDROp optype) { SECStatus status; jbyteArray outputBA = NULL; SECItem keyID = {siBuffer, NULL, 0}; SECItem *input= NULL; SECItem output = {siBuffer, NULL, 0}; /* convert input to SECItem */ if( inputBA == NULL ) { JSS_throw(env, NULL_POINTER_EXCEPTION); goto finish; } input = JSS_ByteArrayToSECItem(env, inputBA); if( input == NULL) { /* exception was thrown */ goto finish; } /* perform the operation*/ if( optype == SDR_ENCRYPT ) { status = PK11SDR_Encrypt(&keyID, input, &output, NULL /*cx*/); } else { PR_ASSERT( optype == SDR_DECRYPT); status = PK11SDR_Decrypt(input, &output, NULL /*cx*/); } if(status != SECSuccess) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Operation failed"); goto finish; } /* convert output to byte array */ outputBA = JSS_SECItemToByteArray(env, &output); finish: if( input != NULL) { SECITEM_FreeItem(input, PR_TRUE /* freeit */); } SECITEM_FreeItem(&output, PR_FALSE /*freeit*/); return outputBA; } JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_crypto_SecretDecoderRing_encrypt( JNIEnv *env, jobject this, jbyteArray plaintextBA) { return doSDR(env, this, plaintextBA, SDR_ENCRYPT); } JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_crypto_SecretDecoderRing_decrypt( JNIEnv *env, jobject this, jbyteArray ciphertextBA) { return doSDR(env, this, ciphertextBA, SDR_DECRYPT); } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/SecretDecoderRing.java000066400000000000000000000053671412550063600255370ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.io.UnsupportedEncodingException; /** * This is a special-purpose interface for NSS. It is used for encrypting * data with a secret key stored in the NSS key database (which is in turn * protected with a password). It thus provides a quick, convenient way * to encrypt stuff your application wants to keep around for its own use: * for example, the list of web passwords stored in the web browser. * *

A dedicated key is used to encrypt all SecretDecoderRing data. * The same key is used for all SDR data, and not for any other data. * This key will be generated the first time it is needed. * *

The cipher used is DES3-EDE (Triple-DES) in CBC mode. The ciphertext * is DER-encoded in the following ASN.1 data structure: *

 *    SEQUENCE {
 *      keyid       OCTET STRING,
 *      alg         AlgorithmIdentifier,
 *      ciphertext  OCTET STRING }
 * 
* *

You must set the password on the Internal Key Storage Token * (aka software token, key3.db) before you use the SecretDecoderRing. */ public class SecretDecoderRing { public static final String encodingFormat = "UTF-8"; /** * Encrypts the given plaintext with the Secret Decoder Ring key stored * in the NSS key database. */ public native byte[] encrypt(byte[] plaintext) throws TokenException; /** * Encrypts the given plaintext string with the Secret Decoder Ring key * stored in the NSS key database. */ public byte[] encrypt(String plaintext) throws TokenException { try { return encrypt(plaintext.getBytes(encodingFormat)); } catch(UnsupportedEncodingException e) { // this shouldn't happen, because we use a universally-supported // charset throw new RuntimeException(e.getMessage()); } } /** * Decrypts the given ciphertext with the Secret Decoder Ring key stored * in the NSS key database. */ public native byte[] decrypt(byte[] ciphertext) throws TokenException; /** * Decrypts the given ciphertext with the Secret Decoder Ring key stored * in the NSS key database, returning the original plaintext string. */ public String decryptToString(byte[] ciphertext) throws TokenException { try { return new String(decrypt(ciphertext), encodingFormat); } catch(UnsupportedEncodingException e) { // this shouldn't happen, because we use a universally-supported // charset throw new RuntimeException(e.getMessage()); } } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/SecretKeyFacade.java000066400000000000000000000013271412550063600251560ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; public class SecretKeyFacade implements javax.crypto.SecretKey { private static final long serialVersionUID = 1L; public SymmetricKey key; public SecretKeyFacade(SymmetricKey symk) { key = symk; } @Override public String getAlgorithm() { return key.getAlgorithm(); } @Override public byte[] getEncoded() { return key.getEncoded(); } @Override public String getFormat() { return key.getFormat(); } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/ShortBufferException.java000066400000000000000000000007061412550063600263040ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; /** * This class is a placeholder for javax.crypto.ShortBufferException until * we move to JDK 1.2. */ public class ShortBufferException extends Exception { private static final long serialVersionUID = 1L; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/Signature.java000066400000000000000000000151471412550063600241420ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Provider; import java.security.PublicKey; import java.security.SignatureException; import java.security.spec.AlgorithmParameterSpec; /** * A class for producing and verifying digital signatures. * Instances of this class can be obtain from CryptoTokens. * * @see org.mozilla.jss.crypto.CryptoToken#getSignatureContext */ public class Signature { protected Signature() { } Signature(SignatureAlgorithm algorithm, SignatureSpi engine) { this.algorithm = algorithm; this.engine = engine; } /** * This is not supported yet. */ public Provider getProvider() { throw new RuntimeException("Signature.getProvider() is not yet implemented"); } /** * Supplying sources of randoms is not supported yet. * public void initSign(PrivateKey privateKey, SecureRandom random) * throws InvalidKeyException, TokenException * { * engine.engineInitSign(privateKey, random); * } */ /** * Initialize the signature context for signing. * * @param privateKey The private key with which to sign. * @exception InvalidKeyException If the key is the wrong type for the * algorithm or does not exist on the token of this signature * context. * @exception TokenException If an error occurred on the token. */ public void initSign(PrivateKey privateKey) throws InvalidKeyException, TokenException { engine.engineInitSign(privateKey); } /** * Initialize the signature context for verifying. * * @param publicKey The public key with which to verify the signature. * @exception InvalidKeyException If the key is the wrong type for the * algorithm. * @exception TokenException If an error occurs on the token. */ public void initVerify(PublicKey publicKey) throws InvalidKeyException, TokenException { engine.engineInitVerify(publicKey); } /** * Set parameters for the signing algorithm. This is currently not * supported or needed. * * @param params Parameters for the signing algorithm. * @exception InvalidAlgorithmParameterException If there is something wrong * with the parameters. * @exception TokenException If an error occurs on the token. */ public void setParameter(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException, TokenException { engine.engineSetParameter(params); } /** * Finish a signing operation and return the signature. * * @exception SignatureException If an error occurs with the signing * operation. * @exception TokenException If an error occurs on the token. * @return The signature. */ public byte[] sign() throws SignatureException, TokenException { return engine.engineSign(); } /** * Finish a signing operation and store the signature in the provided * buffer. * * @param outbuf Buffer to hold the signature * @param offset Offset in buffer at which to store signature. * @param len Number of bytes of buffer available for signature. * @return int The number of bytes placed into outbuf. * @exception SignatureException If an error occurred while signing, or * len was insufficient to contain the signature. * @exception TokenException If an error occurred on the token. */ public int sign(byte[] outbuf, int offset, int len) throws SignatureException, TokenException { return engine.engineSign(outbuf, offset, len); } /** * Finish a verification operation. * * @param signature The signature to be verified. * @return true if the signature is valid, false if it is invalid. * @exception SignatureException If an error occurred with the verification * operation * @exception TokenException If an error occurred on the token. */ public boolean verify(byte[] signature) throws SignatureException, TokenException { return engine.engineVerify(signature); } /** * Provide more data for a signature or verification operation. * * @param b A byte to be signed or verified. * @exception SignatureException If an error occurs in the * signature/verifcation. * @exception TokenException If an error occurs on the token. */ public void update(byte b) throws SignatureException, TokenException { engine.engineUpdate(b); } /** * Provide more data for a signature or verification operation. * * @param data An array of bytes to be signed or verified. * @exception SignatureException If an error occurs in the * signature/verifcation. * @exception TokenException If an error occurs on the token. */ public void update(byte[] data) throws SignatureException, TokenException { engine.engineUpdate(data, 0, data.length); } /** * Provide more data for a signature or verification operation. * * @param data An array of bytes, some of which will be signed or verified. * @param off The beginning offset of the bytes to be signed/verified. * @param len The number of bytes to be signed/verified. * @exception SignatureException If an error occurs in the * signature/verification. * @exception TokenException If an error occurs on the token. */ public void update(byte[] data, int off, int len) throws SignatureException, TokenException { engine.engineUpdate(data, off, len); } /** * Returns the name of the algorithm to be used for signing. */ public String getAlgorithm() { return algorithm.toString(); } /** * Returns the algorithm to be used for signing. */ public SignatureAlgorithm getAlgorithmID() { return algorithm; } /** * Cloning is not supported yet */ @Override protected Object clone() throws CloneNotSupportedException { // no cloning for now throw new CloneNotSupportedException(); } protected SignatureAlgorithm algorithm; protected SignatureSpi engine; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/SignatureAlgorithm.java000066400000000000000000000214231412550063600260030ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.NoSuchAlgorithmException; import java.util.Hashtable; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; /** * Algorithms that can be used for signing. */ public class SignatureAlgorithm extends Algorithm { private static Hashtable oidMap = new Hashtable<>(); protected SignatureAlgorithm(int oidIndex, String name, SignatureAlgorithm signingAlg, DigestAlgorithm digestAlg, OBJECT_IDENTIFIER oid) { super(oidIndex, name, oid); if(signingAlg == null) { this.signingAlg = this; } else { this.signingAlg = signingAlg; } this.digestAlg = digestAlg; oidMap.put(oid, this); } /** * Looks up the signature algorithm with the given OID. * @exception NoSuchAlgorithmException If no algorithm is found with this * OID. */ public static SignatureAlgorithm fromOID(OBJECT_IDENTIFIER oid) throws NoSuchAlgorithmException { Object alg = oidMap.get(oid); if( alg == null ) { throw new NoSuchAlgorithmException(); } return (SignatureAlgorithm) alg; } /** * The raw encryption portion of the signature algorithm. For example, * SignatureAlgorithm.RSASignatureWithMD2Digest.getSigningAlg == * SignatureAlgorithm.RSASignature. */ public Algorithm getSigningAlg() { return signingAlg; } public SignatureAlgorithm getRawAlg() { return signingAlg; } private SignatureAlgorithm signingAlg; /** * The digest portion of the signature algorithm. */ private DigestAlgorithm digestAlg; public DigestAlgorithm getDigestAlg() throws NoSuchAlgorithmException { if (digestAlg == null) { throw new NoSuchAlgorithmException(); } return digestAlg; } public DigestAlgorithm setDigestAlg(DigestAlgorithm alg) throws NoSuchAlgorithmException { if (alg == null) { throw new NoSuchAlgorithmException(); } return digestAlg = alg; } ////////////////////////////////////////////////////////////////////// // Signature Algorithms ////////////////////////////////////////////////////////////////////// /********************************************************************** * Raw RSA signing. This algorithm does not do any hashing, it merely * encrypts its input, which should be a hash. */ public static final SignatureAlgorithm RSASignature = new SignatureAlgorithm(SEC_OID_PKCS1_RSA_ENCRYPTION, "RSA", null, null, OBJECT_IDENTIFIER.PKCS1.subBranch(1) ); /********************************************************************** * Raw DSA signing. This algorithm does not do any hashing, it merely * operates on its input, which should be a hash. */ public static final SignatureAlgorithm DSASignature = new SignatureAlgorithm(SEC_OID_ANSIX9_DSA_SIGNATURE, "DSA", null, null, ANSI_X9_ALGORITHM.subBranch(1) ); /********************************************************************** * Raw EC signing. This algorithm does not do any hashing, it merely * operates on its input, which should be a hash. */ public static final SignatureAlgorithm ECSignature = new SignatureAlgorithm(SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST, "EC", null, null, ANSI_X962_OID.subBranch(2).subBranch(1) ); ////////////////////////////////////////////////////////////////////// public static final SignatureAlgorithm RSASignatureWithMD2Digest = new SignatureAlgorithm(SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION, "RSASignatureWithMD2Digest", RSASignature, DigestAlgorithm.MD2, OBJECT_IDENTIFIER.PKCS1.subBranch(2) ); ////////////////////////////////////////////////////////////////////// public static final SignatureAlgorithm RSASignatureWithMD5Digest = new SignatureAlgorithm(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION, "RSASignatureWithMD5Digest", RSASignature, DigestAlgorithm.MD5, OBJECT_IDENTIFIER.PKCS1.subBranch(4) ); ////////////////////////////////////////////////////////////////////// public static final SignatureAlgorithm RSASignatureWithSHA1Digest = new SignatureAlgorithm(SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION, "RSASignatureWithSHA1Digest", RSASignature, DigestAlgorithm.SHA1, OBJECT_IDENTIFIER.PKCS1.subBranch(5) ); ////////////////////////////////////////////////////////////////////// public static final SignatureAlgorithm DSASignatureWithSHA1Digest = new SignatureAlgorithm(SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST, "DSASignatureWithSHA1Digest", DSASignature, DigestAlgorithm.SHA1, ANSI_X9_ALGORITHM.subBranch(3) ); ////////////////////////////////////////////////////////////////////// public static final SignatureAlgorithm ECSignatureWithSHA1Digest = new SignatureAlgorithm(SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE, "ECSignatureWithSHA1Digest", ECSignature, DigestAlgorithm.SHA1, ANSI_X962_OID.subBranch(4).subBranch(1) ); ////////////////////////////////////////////////////////////////////// public static final SignatureAlgorithm ECSignatureWithSHA256Digest = new SignatureAlgorithm(SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE, "ECSignatureWithSHA256Digest", ECSignature, DigestAlgorithm.SHA256, ANSI_X962_OID.subBranch(4).subBranch(3).subBranch(2) ); ////////////////////////////////////////////////////////////////////// public static final SignatureAlgorithm ECSignatureWithSHA384Digest = new SignatureAlgorithm(SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE, "ECSignatureWithSHA384Digest", ECSignature, DigestAlgorithm.SHA384, ANSI_X962_OID.subBranch(4).subBranch(3).subBranch(3) ); ////////////////////////////////////////////////////////////////////// public static final SignatureAlgorithm ECSignatureWithSHA512Digest = new SignatureAlgorithm(SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE, "ECSignatureWithSHA512Digest", ECSignature, DigestAlgorithm.SHA512, ANSI_X962_OID.subBranch(4).subBranch(3).subBranch(4) ); ////////////////////////////////////////////////////////////////////// public static final SignatureAlgorithm RSASignatureWithSHA256Digest = new SignatureAlgorithm(SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION, "RSASignatureWithSHA256Digest", RSASignature, DigestAlgorithm.SHA256, OBJECT_IDENTIFIER.PKCS1.subBranch(11)); ////////////////////////////////////////////////////////////////////// public static final SignatureAlgorithm RSASignatureWithSHA384Digest = new SignatureAlgorithm(SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION, "RSASignatureWithSHA384Digest", RSASignature, DigestAlgorithm.SHA384, OBJECT_IDENTIFIER.PKCS1.subBranch(12)); ////////////////////////////////////////////////////////////////////// public static final SignatureAlgorithm RSASignatureWithSHA512Digest = new SignatureAlgorithm(SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION, "RSASignatureWithSHA512Digest", RSASignature, DigestAlgorithm.SHA512, OBJECT_IDENTIFIER.PKCS1.subBranch(13)); ////////////////////////////////////////////////////////////////////// /** * Version with no digest set: must call setDigestAlg() after initialization * to choose the proper variant. */ public static final SignatureAlgorithm RSAPSSSignature = new SignatureAlgorithm(SEC_OID_PKCS1_RSA_PSS_SIGNATURE, "RSAPSSSignature", null, null, OBJECT_IDENTIFIER.PKCS1.subBranch(10)); public static final SignatureAlgorithm RSAPSSSignatureWithSHA256Digest = new SignatureAlgorithm(SEC_OID_PKCS1_RSA_PSS_SIGNATURE, "RSAPSSSignatureWithSHA256Digest", null, DigestAlgorithm.SHA256, OBJECT_IDENTIFIER.PKCS1.subBranch(10)); public static final SignatureAlgorithm RSAPSSSignatureWithSHA384Digest = new SignatureAlgorithm(SEC_OID_PKCS1_RSA_PSS_SIGNATURE, "RSAPSSSignatureWithSHA384Digest", null, DigestAlgorithm.SHA384, OBJECT_IDENTIFIER.PKCS1.subBranch(10)); public static final SignatureAlgorithm RSAPSSSignatureWithSHA512Digest = new SignatureAlgorithm(SEC_OID_PKCS1_RSA_PSS_SIGNATURE, "RSAPSSSignatureWithSHA512Digest", null, DigestAlgorithm.SHA512, OBJECT_IDENTIFIER.PKCS1.subBranch(10)); } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/SignatureSpi.java000066400000000000000000000026501412550063600246110ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.*; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; /** * You don't need to use this unless you are hacking JSS. */ public abstract class SignatureSpi { public abstract void engineInitVerify(PublicKey publicKey) throws InvalidKeyException, TokenException; public abstract void engineInitSign(PrivateKey privateKey) throws InvalidKeyException, TokenException; public abstract void engineInitSign(PrivateKey privateKey, SecureRandom random) throws InvalidKeyException, TokenException; public abstract void engineUpdate(byte b) throws SignatureException, TokenException; public abstract void engineUpdate(byte[] b, int off, int len) throws SignatureException, TokenException; public abstract byte[] engineSign() throws SignatureException, TokenException; public abstract int engineSign(byte[] outbuf, int offset, int len) throws SignatureException, TokenException; public abstract boolean engineVerify(byte[] sigBytes) throws SignatureException, TokenException; public abstract void engineSetParameter(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException, TokenException; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/SymmetricKey.java000066400000000000000000000157151412550063600246270ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Hashtable; import org.mozilla.jss.pkcs11.KeyType; import org.mozilla.jss.pkcs11.PKCS11Constants; public interface SymmetricKey extends javax.crypto.SecretKey { public static final Type GENERIC_SECRET = Type.GENERIC_SECRET; public static final Type DES = Type.DES; public static final Type DES3 = Type.DES3; public static final Type RC4 = Type.RC4; public static final Type RC2 = Type.RC2; public static final Type SHA1_HMAC = Type.SHA1_HMAC; public static final Type SHA256_HMAC = Type.SHA256_HMAC; public static final Type SHA384_HMAC = Type.SHA384_HMAC; public static final Type SHA512_HMAC = Type.SHA512_HMAC; public static final Type AES = Type.AES; public Type getType(); public CryptoToken getOwningToken(); public int getStrength(); public int getLength(); public byte[] getKeyData() throws NotExtractableException; public static class NotExtractableException extends Exception { private static final long serialVersionUID = 1L; public NotExtractableException() { super(); } public NotExtractableException(String mesg) { super(mesg); } } @Override String getAlgorithm(); @Override byte[] getEncoded(); @Override String getFormat(); String getNickName(); void setNickName(String nickName); public final static class Type { // all names converted to lowercase for case insensitivity private static Hashtable nameMap = new Hashtable<>(); private static ArrayList allTypes = new ArrayList<>(); private String[] names; private KeyGenAlgorithm keyGenAlg; private KeyType keyType; private Type() { } private Type(String[] names, KeyGenAlgorithm keyGenAlg, KeyType keyType) { this.names = names; this.keyGenAlg = keyGenAlg; this.keyType = keyType; for (String name : names) { nameMap.put(name.toLowerCase(), this); } allTypes.add(this); } public static final Type GENERIC_SECRET = new Type(new String[] { "GenericSecret", "GENERIC_SECRET" }, KeyGenAlgorithm.GENERIC_SECRET, KeyType.GENERIC_SECRET); public static final Type DES = new Type(new String[] { "DES" }, KeyGenAlgorithm.DES, KeyType.DES); public static final Type DES3 = new Type(new String[] { "DESede", "TDES", "3DES", "DES3" }, KeyGenAlgorithm.DES3, KeyType.DES3); public static final Type DESede = DES3; public static final Type RC4 = new Type(new String[] { "RC4" }, KeyGenAlgorithm.RC4, KeyType.RC4); public static final Type RC2 = new Type(new String[] { "RC2" }, KeyGenAlgorithm.RC2, KeyType.RC4); public static final Type SHA1_HMAC = new Type( new String[] { "SHA1_HMAC", "SHA1-HMAC", "SHA1HMAC", "HMAC_SHA1", "HMAC-SHA1", "HMACSHA1" }, KeyGenAlgorithm.SHA1_HMAC, KeyType.SHA1_HMAC); public static final Type SHA256_HMAC = new Type( new String[] { "SHA256_HMAC", "SHA256-HMAC", "SHA256HMAC", "HMAC_SHA256", "HMAC-SHA256", "HMACSHA256" }, KeyGenAlgorithm.SHA256_HMAC, KeyType.SHA256_HMAC); public static final Type SHA384_HMAC = new Type( new String[] { "SHA384_HMAC", "SHA384-HMAC", "SHA384HMAC", "HMAC_SHA384", "HMAC-SHA384", "HMACSHA384" }, KeyGenAlgorithm.SHA384_HMAC, KeyType.SHA384_HMAC); public static final Type SHA512_HMAC = new Type( new String[] { "SHA512_HMAC", "SHA512-HMAC", "SHA512HMAC", "HMAC_SHA512", "HMAC-SHA512", "HMACSHA512" }, KeyGenAlgorithm.SHA512_HMAC, KeyType.SHA512_HMAC); public static final Type PBA_SHA1_HMAC = new Type(new String[] { "PBA_SHA1_HMAC" }, KeyGenAlgorithm.PBA_SHA1_HMAC, null); public static final Type AES = new Type(new String[] { "AES" }, KeyGenAlgorithm.AES, KeyType.AES); @Override public String toString() { return names[0]; } public String[] getAliases() { return names; } public KeyGenAlgorithm getKeyGenAlg() throws NoSuchAlgorithmException { if (keyGenAlg == null) { throw new NoSuchAlgorithmException(names[0]); } return keyGenAlg; } public KeyType getKeyType() { return keyType; } public static Type fromName(String name) throws NoSuchAlgorithmException { Object type = nameMap.get(name.toLowerCase()); if (type == null) { throw new NoSuchAlgorithmException(); } else { return (Type) type; } } public static Type fromKeyType(KeyType type) { for (Type current : allTypes) { if (current.getKeyType() == type) { return current; } } return null; } } /** * In PKCS #11, each key can be marked with the operations it will * be used to perform. Some tokens require that a key be marked for * an operation before the key can be used to perform that operation; * other tokens don't care. * *

* When you unwrap a symmetric key, you must specify which one of these * operations it will be used to perform. */ public enum Usage { ENCRYPT(PKCS11Constants.CKF_ENCRYPT, PKCS11Constants.CKA_ENCRYPT), DECRYPT(PKCS11Constants.CKF_DECRYPT, PKCS11Constants.CKA_DECRYPT), WRAP(PKCS11Constants.CKF_WRAP, PKCS11Constants.CKA_WRAP), UNWRAP( PKCS11Constants.CKF_UNWRAP, PKCS11Constants.CKA_UNWRAP), SIGN(PKCS11Constants.CKF_SIGN, PKCS11Constants.CKA_SIGN), VERIFY( PKCS11Constants.CKF_VERIFY, PKCS11Constants.CKA_VERIFY); private final long value; private final long cka_value; Usage(long value, long cka_value) { this.value = value; this.cka_value = cka_value; } /** * @deprecated Use ordinal() instead. */ @Deprecated public int getVal() { return ordinal(); } /** * Get PKCS #11 CKF_ value. */ public long value() { return value; } /** * Get PKCS #11 CKA_ value. * * @deprecated Use value() to get PKCS #11 CKF_ value instead. */ @Deprecated public long getPKCS11Constant() { return cka_value; } } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/SymmetricKeyDeriver.java000066400000000000000000000060741412550063600261460ustar00rootroot00000000000000/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * 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 Services for Java. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.jss.crypto; import java.security.InvalidKeyException; public interface SymmetricKeyDeriver { /* Use with the encrypt type mechanisms Example: initDerive( symKey, (PKCS11Constants.CKM_DES3_ECB_ENCRYPT_DATA) 4354L, derivationData, null, PKCS11Constants.CKM_DES3_ECB, PKCS11Constants.CKA_DERIVE, 16); */ public abstract void initDerive(SymmetricKey baseKey, long deriveMech, byte[] param, byte[] iv, long targetMech, long operation, long keySize) throws InvalidKeyException; /* Use with key extraction and key concatanation mechanisms Example: param: byte array that has the bit position of where to extract initDerive( derivedKey, PKCS11Constants.CKM_EXTRACT_KEY_FROM_KEY,param,null, PKCS11Constants.CKA_ENCRYPT, PKCS11Constants.CKA_DERIVE,8); initDerive( baseSymKey,secondarySymKey, PKCS11Constants.CKM_CONCATENATE_BASE_AND_KEY,null,null, PKCS11Constants.CKM_DES3_ECB, PKCS11Constants.CKA_DERIVE,0); */ public abstract void initDerive(SymmetricKey baseKey, SymmetricKey secondaryKey, long deriveMech, byte[] param, byte[] iv, long targetMech, long operation, long keySize) throws InvalidKeyException; public abstract SymmetricKey derive() throws TokenException; } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/TokenCertificate.java000066400000000000000000000017571412550063600254260ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; /** * An X509 Certificate that lives on a PKCS #11 token. * Many of the X509Certificates returned by JSS calls are actually * TokenCertificates. * To find out if an X509Certificate is a TokenCertificate, use * instanceof. */ public interface TokenCertificate extends X509Certificate { /** * Returns the unique ID of this key. Unique IDs can be used to match * certificates to keys. * * @see org.mozilla.jss.crypto.PrivateKey#getUniqueID */ public abstract byte[] getUniqueID(); /** * Returns the CryptoToken that owns this certificate. Cryptographic * operations with this key may only be performed on the token that * owns the key. */ public abstract CryptoToken getOwningToken(); } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/TokenException.java000066400000000000000000000017401412550063600251320ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; /** * This class indicates that an unknown error occurred on a CryptoToken. * The nature of CryptoTokens makes such unpredictable errors possible. * For example, a smartcard could be yanked out of its slot in the middle * of a cryptographic operation. */ public class TokenException extends Exception { private static final long serialVersionUID = 1L; public TokenException() { super(); } public TokenException(String mesg) { super(mesg); } public TokenException(String mesg, Throwable cause) { super(mesg, cause); } public TokenException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(mesg, cause, enableSuppression, writableStackTrace); } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/TokenRuntimeException.java000066400000000000000000000020121412550063600264670ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; /** * This class indicates that an unknown error occurred on a CryptoToken. * The nature of CryptoTokens makes such unpredictable errors possible. * For example, a smartcard could be yanked out of its slot in the middle * of a cryptographic operation. */ public class TokenRuntimeException extends RuntimeException { private static final long serialVersionUID = 1L; public TokenRuntimeException() { super(); } public TokenRuntimeException(String mesg) { super(mesg); } public TokenRuntimeException(String mesg, Throwable cause) { super(mesg, cause); } public TokenRuntimeException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(mesg, cause, enableSuppression, writableStackTrace); } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/TokenSupplier.java000066400000000000000000000014111412550063600247720ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; /** * An interface that allows providers to access CryptoManager without actually * knowing about CryptoManager. This is necessary to prevent cyclic * dependencies. CryptoManager knows about the providers, so the providers * can't know about CryptoManager. Instead, CryptoManager implements * this interface. */ public interface TokenSupplier { public CryptoToken getInternalCryptoToken(); public JSSSecureRandom getSecureRNG(); public CryptoToken getThreadToken(); public void setThreadToken(CryptoToken token); } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/TokenSupplierManager.java000066400000000000000000000016441412550063600262750ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; /** * The org.mozilla.jss.provider package comes before CryptoManager in * the dependency list, so this class is used to allow them to access * CryptoManager sneakily. When CryptoManager initializes, it registers * itself as a token supplier with setTokenSupplier. Then * the providers call getTokenSupplier when they need to use * CryptoManager. CryptoManager implements the TokenSupplier interface. */ public class TokenSupplierManager { static private TokenSupplier supplier; static public void setTokenSupplier(TokenSupplier ts) { supplier = ts; } static public TokenSupplier getTokenSupplier() { return supplier; } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/Tunnel.java000066400000000000000000000011271412550063600234370ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; /** * This is a private JSS class that allows the pkcs11 package access * to some of the * package methods in the crypto package. A friend declaration would * have been ideal. */ public class Tunnel { protected static Signature ConstructSignature( SignatureAlgorithm alg, SignatureSpi engine) { return new Signature(alg, engine); } } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/X509Certificate.java000066400000000000000000000027411412550063600250050ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.crypto; import java.math.BigInteger; import java.security.Principal; import java.security.cert.CertificateEncodingException; /** * Certificates handled by JSS. All certificates handled by JSS are * of this type. */ public interface X509Certificate { /** * @return The DER encoding of this certificate. * @throws CertificateEncodingException If an error occurred. */ public byte[] getEncoded() throws CertificateEncodingException; /** * @return The nickname of this certificate (could be null). */ public abstract String getNickname(); /** * @return The Public Key from this certificate. */ public abstract java.security.PublicKey getPublicKey(); /** * @return The RFC 1485 ASCII encoding of the Subject Name. */ public abstract Principal getSubjectDN(); /** * @return The RFC 1485 ASCII encoding of the issuer's Subject Name. */ public abstract Principal getIssuerDN(); /** * @return The serial number of this certificate. */ public abstract BigInteger getSerialNumber(); /** * @return the version number of this X.509 certificate. * 0 means v1, 1 means v2, 2 means v3. */ public abstract int getVersion(); } jss-5.0.0/src/main/java/org/mozilla/jss/crypto/package.html000066400000000000000000000004751412550063600236150ustar00rootroot00000000000000 Generic cryptographic operations, such as signing and key pair generation. jss-5.0.0/src/main/java/org/mozilla/jss/jssconfig.h.in000066400000000000000000000005611412550063600225530ustar00rootroot00000000000000#ifndef _CONFIG_H #define _CONFIG_H #cmakedefine HAVE_NSS_CIPHER_SUITE_INFO_KDFHASH 1 #cmakedefine HAVE_NSS_CHANNEL_INFO_ORIGINAL_KEA_GROUP 1 #cmakedefine HAVE_NSS_CHANNEL_INFO_PEER_DELEG_CRED 1 #cmakedefine HAVE_NSS_PRELIMINARY_CHANNEL_INFO_ZERO_RTT_CIPHER_SUITE 1 #cmakedefine HAVE_NSS_PRELIMINARY_CHANNEL_INFO_PEER_DELEG_CRED 1 #cmakedefine HAVE_NSS_OAEP 1 #endif jss-5.0.0/src/main/java/org/mozilla/jss/netscape/000077500000000000000000000000001412550063600216105ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/000077500000000000000000000000001412550063600234575ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/extensions/000077500000000000000000000000001412550063600256565ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/extensions/AccessDescription.java000066400000000000000000000047701412550063600321360ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.extensions; import java.io.IOException; import java.io.Serializable; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; import org.mozilla.jss.netscape.security.x509.GeneralName; public class AccessDescription implements Serializable { ObjectIdentifier mOID = null; GeneralName mLocation = null; AccessDescription(ObjectIdentifier oid, GeneralName location) { mOID = oid; mLocation = location; } public ObjectIdentifier getMethod() { return mOID; } public GeneralName getLocation() { return mLocation; } /** * For serialization: * Note that GeneralName is not serializable. That is * why we need to define our own serialization method. */ private void writeObject(java.io.ObjectOutputStream out) throws IOException { try (DerOutputStream seq = new DerOutputStream(); DerOutputStream tmp = new DerOutputStream()) { tmp.putOID(mOID); mLocation.encode(tmp); seq.write(DerValue.tag_Sequence, tmp); out.write(seq.toByteArray()); } } /** * For serialization * Note that GeneralName is not serializable. That is * why we need to define our own serialization method. */ private void readObject(java.io.ObjectInputStream in) throws IOException { DerValue val = new DerValue(in); DerValue seq = val.data.getDerValue(); mOID = seq.getOID(); DerValue derLoc = val.data.getDerValue(); mLocation = new GeneralName(derLoc); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/extensions/AuthInfoAccessExtension.java000066400000000000000000000223121412550063600332550ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.extensions; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; import org.mozilla.jss.netscape.security.x509.CertAttrSet; import org.mozilla.jss.netscape.security.x509.Extension; import org.mozilla.jss.netscape.security.x509.GeneralName; import org.mozilla.jss.netscape.security.x509.URIName; import org.mozilla.jss.netscape.security.util.Utils; /** * This represents the authority information access extension * as defined in RFC2459. * * id-pkix OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) dod(6) * internet(1) security(5) mechanisms(5) * pkix(7) } } * id-pe OBJECT IDENTIFIER ::= { id-pkix 1 } * id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 } * AuthorityInfoAccessSyntax ::= SEQUENCE SIZE (1..MAX) OF AccessDescription * AccessDescription ::= SEQUENCE { * accessMethod OBJECT IDENTIFIER, * accessLocation GeneralName * } * id-ad OBJECT IDENTIFIER ::= { id-pkix 48 } * id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 } * id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 } * * Need to make sure the following is added to CMS.cfg: * oidmap.auth_info_access.class=com.netscape.certsrv.cert.AuthInfoAccessExtension * oidmap.auth_info_access.oid=1.3.6.1.5.5.7.1.1 * * @author thomask * @version $Revision$, $Date$ */ public class AuthInfoAccessExtension extends Extension implements CertAttrSet { private static final long serialVersionUID = 7373316523212538446L; public static final String NAME = "AuthInfoAccessExtension"; public static final String NAME2 = "AuthorityInformationAccess"; public static final int OID_OCSP[] = { 1, 3, 6, 1, 5, 5, 7, 48, 1 }; public static final ObjectIdentifier METHOD_OCSP = new ObjectIdentifier(OID_OCSP); public static final int OID_CA_ISSUERS[] = { 1, 3, 6, 1, 5, 5, 7, 48, 2 }; public static final ObjectIdentifier METHOD_CA_ISSUERS = new ObjectIdentifier(OID_CA_ISSUERS); public static final int OID[] = { 1, 3, 6, 1, 5, 5, 7, 1, 1 }; public static final ObjectIdentifier ID = new ObjectIdentifier(OID); private Vector mDesc = new Vector(); /** * Create the extension from the passed DER encoded value of the same. * * @param critical true if the extension is to be treated as critical. */ public AuthInfoAccessExtension(boolean critical) { this.extensionId = ID; this.critical = critical; this.extensionValue = null; // build this when encodeThis() is called } /** * Create the extension from the passed DER encoded value of the same. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public AuthInfoAccessExtension(Boolean critical, Object value) throws IOException { this.extensionId = ID; this.critical = critical.booleanValue(); this.extensionValue = ((byte[]) value).clone(); decodeThis(); } /** * Sets extension attribute. */ @Override public void set(String name, Object obj) throws CertificateException { // NOT USED } /** * Retrieves extension attribute. */ @Override public Object get(String name) throws CertificateException { // NOT USED return null; } /** * Deletes attribute. */ @Override public void delete(String name) throws CertificateException { // NOT USED } /** * Decodes this extension. */ @Override public void decode(InputStream in) throws IOException { // NOT USED } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { // NOT USED return null; } /** * Return the name of this attribute. */ @Override public String getName() { return NAME; } /** * Adds Access Description. */ public void addAccessDescription( ObjectIdentifier method, GeneralName gn) { clearValue(); mDesc.addElement(new AccessDescription(method, gn)); } public AccessDescription getAccessDescription(int pos) { return mDesc.elementAt(pos); } /** * Returns the number of access description. */ public int numberOfAccessDescription() { return mDesc.size(); } private void decodeThis() throws IOException { DerValue val = new DerValue(this.extensionValue); if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding of AuthInfoAccess extension"); } while (val.data.available() != 0) { DerValue seq = val.data.getDerValue(); ObjectIdentifier method = seq.data.getDerValue().getOID(); GeneralName gn = new GeneralName(seq.data.getDerValue()); addAccessDescription(method, gn); } } private void encodeThis() throws IOException { try (DerOutputStream seq = new DerOutputStream(); DerOutputStream tmp = new DerOutputStream()) { for (int i = 0; i < mDesc.size(); i++) { DerOutputStream tmp0 = new DerOutputStream(); AccessDescription ad = mDesc.elementAt(i); tmp0.putOID(ad.getMethod()); ad.getLocation().encode(tmp0); tmp.write(DerValue.tag_Sequence, tmp0); } seq.write(DerValue.tag_Sequence, tmp); this.extensionValue = seq.toByteArray(); } } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Returns a printable representation of the AuthInfoAccess. */ @Override public String toString() { StringBuffer s = new StringBuffer(); String b = super.toString() + "AuthInfoAccess [\n"; s.append(b); for (int i = 0; i < mDesc.size(); i++) { AccessDescription ad = mDesc.elementAt(i); s.append("(" + i + ")"); s.append(" "); s.append(ad.getMethod().toString() + " " + ad.getLocation().toString()); } return (s.toString() + "]\n"); } public static void main(String[] argv) { AuthInfoAccessExtension aia = new AuthInfoAccessExtension(false); GeneralName ocspName = new GeneralName(new URIName("http://ocsp.netscape.com")); aia.addAccessDescription(METHOD_OCSP, ocspName); GeneralName caIssuersName = new GeneralName(new URIName("http://ocsp.netscape.com")); aia.addAccessDescription(METHOD_CA_ISSUERS, caIssuersName); ByteArrayOutputStream os = new ByteArrayOutputStream(); try { aia.encode(os); System.out.println(Utils.base64encode(os.toByteArray(), true)); } catch (IOException e) { System.out.println(e.toString()); } try { // test serialization ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(aia); ByteArrayInputStream bis = new ByteArrayInputStream( bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); AuthInfoAccessExtension clone = (AuthInfoAccessExtension) ois.readObject(); System.out.println(clone); } catch (Exception e) { System.out.println(e.toString()); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/extensions/CertInfo.java000066400000000000000000000117241412550063600302370ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.extensions; import java.io.IOException; import java.math.BigInteger; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.util.Date; import org.mozilla.jss.netscape.security.x509.AlgorithmId; import org.mozilla.jss.netscape.security.x509.CertificateAlgorithmId; import org.mozilla.jss.netscape.security.x509.CertificateIssuerName; import org.mozilla.jss.netscape.security.x509.CertificateSerialNumber; import org.mozilla.jss.netscape.security.x509.CertificateSubjectName; import org.mozilla.jss.netscape.security.x509.CertificateValidity; import org.mozilla.jss.netscape.security.x509.CertificateVersion; import org.mozilla.jss.netscape.security.x509.X500Name; import org.mozilla.jss.netscape.security.x509.X509CertInfo; /** * Extends X509CertInfo class so that minimal fields are initialized at * creation time so an object of this type is always serializable. */ public class CertInfo extends X509CertInfo { /** * */ private static final long serialVersionUID = -2883888348288591989L; public static final CertificateSubjectName SERIALIZE_SUBJECT; public static final CertificateIssuerName SERIALIZE_ISSUER; public static final CertificateValidity SERIALIZE_VALIDITY; public static final CertificateSerialNumber SERIALIZE_SERIALNO; public static final CertificateAlgorithmId SERIALIZE_ALGOR; public static final CertificateVersion FORCE_VERSION_3; static { try { // force version 3 FORCE_VERSION_3 = new CertificateVersion(CertificateVersion.V3); SERIALIZE_SUBJECT = new CertificateSubjectName( new X500Name("cn=uninitialized")); SERIALIZE_ISSUER = new CertificateIssuerName( new X500Name("cn=uninitialized")); SERIALIZE_VALIDITY = new CertificateValidity(new Date(0), new Date(0)); SERIALIZE_SERIALNO = new CertificateSerialNumber(new BigInteger("0")); SERIALIZE_ALGOR = new CertificateAlgorithmId(AlgorithmId.get("MD5withRSA")); } catch (IOException e) { // should never happen. If does, system is hosed. System.out.println("**** Impossible Error encountered ****"); throw new RuntimeException(e.toString()); } catch (NoSuchAlgorithmException e) { // should never happen. If does, system is hosed. System.out.println("**** Impossible Error encountered ****"); throw new RuntimeException(e.toString()); } } /** * Initializes most fields required by der encoding so object will * serialize properly. */ // XXX should write a class to use something else for serialization // but this is faster and done now for the time crunch. public CertInfo() { super(); makeSerializable(this); } public static void makeSerializable(X509CertInfo certinfo) { try { // force version 3. certinfo.set(X509CertInfo.VERSION, FORCE_VERSION_3); if (certinfo.get(X509CertInfo.SERIAL_NUMBER) == null) { certinfo.set(X509CertInfo.SERIAL_NUMBER, SERIALIZE_SERIALNO); } if (certinfo.get(X509CertInfo.ALGORITHM_ID) == null) { certinfo.set(X509CertInfo.ALGORITHM_ID, SERIALIZE_ALGOR); } if (certinfo.get(X509CertInfo.ISSUER) == null) { certinfo.set(X509CertInfo.ISSUER, SERIALIZE_ISSUER); } if (certinfo.get(X509CertInfo.VALIDITY) == null) { certinfo.set(X509CertInfo.VALIDITY, SERIALIZE_VALIDITY); } // set subject name anyway - it'll get overwritten. if (certinfo.get(X509CertInfo.SUBJECT) == null) { certinfo.set(X509CertInfo.SUBJECT, SERIALIZE_SUBJECT); } // key is set later in the request. } // these exceptions shouldn't happen here unless the // whole process is hosed. catch (CertificateException e) { } catch (IOException e) { } } } CertificateRenewalWindowExtension.java000066400000000000000000000133061412550063600352720ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/extensions// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.extensions; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Date; import java.util.Enumeration; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; import org.mozilla.jss.netscape.security.x509.CertAttrSet; import org.mozilla.jss.netscape.security.x509.Extension; /** * This represents the CertificateRenewalWindow extension * as defined in draft-thayes-cert-renewal-00 * * CertificateRenewalWindow ::= SEQUENCE { * beginTime GeneralizedTime, * endTime GeneralizedTime OPTIONAL } * * @author thomask * @version $Revision$, $Date$ */ public class CertificateRenewalWindowExtension extends Extension implements CertAttrSet { private static final long serialVersionUID = 4470220533545299271L; public static final String NAME = "CertificateRenewalWindow"; public static final int OID[] = { 2, 16, 840, 1, 113730, 1, 15 }; public static final ObjectIdentifier ID = new ObjectIdentifier(OID); private Date mBeginTime = null; private Date mEndTime = null; // optional public CertificateRenewalWindowExtension(boolean critical, Date beginTime, Date endTime) throws IOException { this.extensionId = ID; this.critical = critical; mBeginTime = beginTime; mEndTime = endTime; encodeThis(); } public CertificateRenewalWindowExtension(boolean critical) { this.extensionId = ID; this.critical = critical; this.extensionValue = null; // build this when encodeThis() is called } public CertificateRenewalWindowExtension(Boolean critical, Object value) throws IOException { this.extensionId = ID; this.critical = critical.booleanValue(); this.extensionValue = ((byte[]) value).clone(); decodeThis(); } @Override public String getName() { return NAME; } /** * Sets extension attribute. */ @Override public void set(String name, Object obj) throws CertificateException { // NOT USED } /** * Retrieves extension attribute. */ @Override public Object get(String name) throws CertificateException { // NOT USED return null; } /** * Deletes attribute. */ @Override public void delete(String name) throws CertificateException { // NOT USED } /** * Decodes this extension. */ @Override public void decode(InputStream in) throws IOException { // NOT USED } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { // NOT USED return null; } public Date getBeginTime() { return mBeginTime; } public Date getEndTime() { return mEndTime; } public void setBeginTime(Date d) { mBeginTime = d; } public void setEndTime(Date d) { mEndTime = d; } private void decodeThis() throws IOException { DerValue val = new DerValue(this.extensionValue); if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding of CertificateWindow extension"); } while (val.data.available() != 0) { if (mBeginTime == null) { mBeginTime = val.data.getGeneralizedTime(); } else { mEndTime = val.data.getGeneralizedTime(); } } } private void encodeThis() throws IOException { try (DerOutputStream seq = new DerOutputStream(); DerOutputStream tmp = new DerOutputStream()) { tmp.putGeneralizedTime(mBeginTime); if (mEndTime != null) { tmp.putGeneralizedTime(mEndTime); } seq.write(DerValue.tag_Sequence, tmp); this.extensionValue = seq.toByteArray(); } } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Returns a printable representation of the CertificateRenewalWindow. */ @Override public String toString() { String s = super.toString() + "CertificateRenewalWindow [\n"; s += "BeginTime: " + mBeginTime + "\n"; if (mEndTime != null) { s += "EndTime: " + mEndTime; } return (s + "]\n"); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/extensions/CertificateScopeEntry.java000066400000000000000000000057121412550063600327640ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.extensions; import java.io.IOException; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.x509.GeneralName; /** * This represents the CertificateScopeOfUse extension * as defined in draft-thayes-cert-scope-00 * * CertificateScopeEntry ::= SEQUENCE { * name GeneralName, -- pattern, as for NameConstraints * portNumber INTEGER OPTIONAL * } * CertificateScopeOfUse ::= SEQUENCE OF CertificateScopeEntry * * @author thomask * @version $Revision$, $Date$ */ public class CertificateScopeEntry { private GeneralName mGn = null; private BigInt mPort = null; /** * Constructs scope with der value. */ public CertificateScopeEntry(DerValue val) throws IOException { if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for PolicyQualifierInfo."); } DerValue gn = val.data.getDerValue(); mGn = new GeneralName(gn); if (val.data.available() != 0) { mPort = val.data.getInteger(); } } /** * Constructs scope wit */ public CertificateScopeEntry(GeneralName gn, BigInt port) { mGn = gn; mPort = port; // optional } public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); mGn.encode(tmp); if (mPort != null) { tmp.putInteger(mPort); } out.write(DerValue.tag_Sequence, tmp); } /** * Returns a GeneralName */ public GeneralName getGeneralName() { return mGn; } /** * Returns a port */ public BigInt getPort() { return mPort; } /** * Returns a printable representation of the CertificateRenewalWindow. */ @Override public String toString() { String s = super.toString() + "CertificateScopeEntry [\n"; s += "GeneralName: " + mGn; if (mPort != null) { s += "PortNumber: " + mPort; } return (s + "]\n"); } } CertificateScopeOfUseExtension.java000066400000000000000000000142021412550063600345140ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/extensions// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.extensions; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; import org.mozilla.jss.netscape.security.x509.CertAttrSet; import org.mozilla.jss.netscape.security.x509.Extension; import org.mozilla.jss.netscape.security.x509.OIDMap; /** * This represents the CertificateScopeOfUse extension * as defined in draft-thayes-cert-scope-00 * * CertificateScopeEntry ::= SEQUENCE { * name GeneralName, -- pattern, as for NameConstraints * portNumber INTEGER OPTIONAL * } * CertificateScopeOfUse ::= SEQUENCE OF CertificateScopeEntry * * @author thomask * @version $Revision$, $Date$ */ public class CertificateScopeOfUseExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 2143292831971567770L; public static final String NAME = "CertificateScopeOfUse"; public static final int OID[] = { 2, 16, 840, 1, 113730, 1, 17 }; public static final ObjectIdentifier ID = new ObjectIdentifier(OID); private Vector mEntries = null; static { try { OIDMap.addAttribute(CertificateScopeOfUseExtension.class.getName(), ID.toString(), NAME); } catch (CertificateException e) { } } public CertificateScopeOfUseExtension(boolean critical, Vector scopeEntries) throws IOException { this.extensionId = ID; this.critical = critical; this.extensionValue = null; // build this when encodeThis() is called mEntries = scopeEntries; encodeThis(); } public CertificateScopeOfUseExtension(boolean critical) { this.extensionId = ID; this.critical = critical; this.extensionValue = null; // build this when encodeThis() is called } public CertificateScopeOfUseExtension(Boolean critical, Object value) throws IOException { this.extensionId = ID; this.critical = critical.booleanValue(); this.extensionValue = ((byte[]) value).clone(); decodeThis(); } @Override public String getName() { return NAME; } public Vector getCertificateScopeEntries() { return mEntries; } /** * Sets extension attribute. */ @Override public void set(String name, Object obj) throws CertificateException { // NOT USED } /** * Retrieves extension attribute. */ @Override public Object get(String name) throws CertificateException { // NOT USED return null; } /** * Deletes attribute. */ @Override public void delete(String name) throws CertificateException { // NOT USED } /** * Decodes this extension. */ @Override public void decode(InputStream in) throws IOException { // NOT USED } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { // NOT USED return null; } private void decodeThis() throws IOException { DerValue val = new DerValue(this.extensionValue); if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding of CertificateWindow extension"); } mEntries = new Vector(); while (val.data.available() != 0) { mEntries.addElement(new CertificateScopeEntry( val.data.getDerValue())); } } private void encodeThis() throws IOException { try (DerOutputStream seq = new DerOutputStream(); DerOutputStream tmp = new DerOutputStream()) { if (mEntries == null) throw new IOException("Invalid Scope Entries"); for (int i = 0; i < mEntries.size(); i++) { CertificateScopeEntry se = mEntries.elementAt(i); se.encode(tmp); } seq.write(DerValue.tag_Sequence, tmp); this.extensionValue = seq.toByteArray(); } } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Returns a printable representation of the CertificateRenewalWindow. */ @Override public String toString() { StringBuffer s = new StringBuffer(super.toString() + "CertificateUseOfScope [\n"); if (mEntries != null) { for (int i = 0; i < mEntries.size(); i++) { CertificateScopeEntry se = mEntries.elementAt(i); s.append(se.toString()); } } return (s.toString() + "]\n"); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/extensions/ExtendedKeyUsageExtension.java000066400000000000000000000157111412550063600336210ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.extensions; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; import org.mozilla.jss.netscape.security.x509.CertAttrSet; import org.mozilla.jss.netscape.security.x509.Extension; import org.mozilla.jss.netscape.security.x509.OIDMap; /** * This represents the extended key usage extension. */ public class ExtendedKeyUsageExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 765403075764697489L; public static final String OID = "2.5.29.37"; public static final String NAME = OIDMap.EXT_KEY_USAGE_NAME; public static final String OID_OCSPSigning = "1.3.6.1.5.5.7.3.9"; public static final String OID_CODESigning = "1.3.6.1.5.5.7.3.3"; public static final int OID_OCSP_SIGNING_STR[] = { 1, 3, 6, 1, 5, 5, 7, 3, 9 }; public static final ObjectIdentifier OID_OCSP_SIGNING = new ObjectIdentifier(OID_OCSP_SIGNING_STR); public static final int OID_CODE_SIGNING_STR[] = { 1, 3, 6, 1, 5, 5, 7, 3, 3 }; public static final ObjectIdentifier OID_CODE_SIGNING = new ObjectIdentifier(OID_OCSP_SIGNING_STR); private Vector oidSet = null; private byte mCached[] = null; static { try { OIDMap.addAttribute(ExtendedKeyUsageExtension.class.getName(), OID, ExtendedKeyUsageExtension.NAME); } catch (CertificateException e) { } } public ExtendedKeyUsageExtension() throws IOException { this(false, null); } public ExtendedKeyUsageExtension(boolean crit, Vector oids) throws IOException { try { extensionId = ObjectIdentifier.getObjectIdentifier(OID); } catch (IOException e) { // never here } critical = crit; if (oids != null) { oidSet = new Vector(oids); } else { oidSet = new Vector(); } encodeExtValue(); } public ExtendedKeyUsageExtension(Boolean crit, Object byteVal) throws IOException { extensionId = ObjectIdentifier.getObjectIdentifier(OID); critical = crit.booleanValue(); extensionValue = ((byte[]) byteVal).clone(); decodeThis(); } @Override public void setCritical(boolean newValue) { if (critical != newValue) { critical = newValue; mCached = null; } } public Enumeration getOIDs() { if (oidSet == null) return null; return oidSet.elements(); } public void deleteAllOIDs() { if (oidSet == null) return; oidSet.clear(); } public void addOID(ObjectIdentifier oid) { if (oidSet == null) { oidSet = new Vector(); } if (oidSet.contains(oid)) return; oidSet.addElement(oid); mCached = null; } @Override public void encode(DerOutputStream out) throws IOException { if (mCached == null) { encodeExtValue(); super.encode(out); mCached = out.toByteArray(); } } @Override public String toString() { String presentation = "oid=" + ExtendedKeyUsageExtension.OID + " "; if (critical) { presentation += "critical=true"; } if (extensionValue != null) { StringBuffer extByteValue = new StringBuffer(" val="); for (int i = 0; i < extensionValue.length; i++) { extByteValue.append(extensionValue[i] + " "); } presentation += extByteValue.toString(); } return presentation; } @Override public void decode(InputStream in) throws CertificateException, IOException { } @Override public void encode(OutputStream out) throws CertificateException, IOException { if (mCached == null) { DerOutputStream temp = new DerOutputStream(); encode(temp); } out.write(mCached); } @Override public void set(String name, Object obj) throws CertificateException, IOException { // NOT USED } @Override public Object get(String name) throws CertificateException, IOException { // NOT USED return null; } @Override public Enumeration getAttributeNames() { return null; } @Override public String getName() { return NAME; } @Override public void delete(String name) throws CertificateException, IOException { // NOT USED } private void decodeThis() throws IOException { DerValue val = new DerValue(this.extensionValue); if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding of AuthInfoAccess extension"); } if (oidSet == null) oidSet = new Vector(); while (val.data.available() != 0) { DerValue oidVal = val.data.getDerValue(); oidSet.addElement(oidVal.getOID()); } } private void encodeExtValue() throws IOException { DerOutputStream out = new DerOutputStream(); DerOutputStream temp = new DerOutputStream(); if (!oidSet.isEmpty()) { Enumeration oidList = oidSet.elements(); try { while (oidList.hasMoreElements()) { temp.putOID(oidList.nextElement()); } } catch (IOException ex) { ex.printStackTrace(); } } try { out.write(DerValue.tag_Sequence, temp); } catch (IOException ex) { } finally { out.close(); } extensionValue = out.toByteArray(); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/extensions/GenericASN1Extension.java000066400000000000000000000371051412550063600324230ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.extensions; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.security.cert.CertificateException; import java.text.DateFormat; import java.text.ParseException; import java.util.Enumeration; import java.util.Hashtable; import java.util.StringTokenizer; import java.util.Vector; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; import org.mozilla.jss.netscape.security.x509.CertAttrSet; import org.mozilla.jss.netscape.security.x509.Extension; import org.mozilla.jss.netscape.security.x509.OIDMap; /** * Represent the AsnInteger Extension. */ public class GenericASN1Extension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 8047548816784949009L; protected static final int MAX_ATTR = 10; protected static final String PROP_CRITICAL = "critical"; protected static final String PROP_NAME = "name"; protected static final String PROP_OID = "oid"; protected static final String PROP_PATTERN = "pattern"; protected static final String PROP_ATTRIBUTE = "attribute"; protected static final String PROP_TYPE = "type"; protected static final String PROP_SOURCE = "source"; protected static final String PROP_VALUE = "value"; protected static final String PROP_PREDICATE = "predicate"; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ private String name; public String OID = null; public static Hashtable mConfig = null; public String pattern = null; private int index = 0; // Encode this value private void encodeThis() throws IOException, ParseException { this.extensionValue = encodePattern(); } // Encode pattern private byte[] encodePattern() throws IOException, ParseException { DerOutputStream tmp = new DerOutputStream(); String type = null; String value = null; String source = null; while (index < pattern.length()) { char ch = pattern.charAt(index); switch (ch) { case '{': index++; byte[] buff = encodePattern(); tmp.putDerValue(new DerValue(buff)); break; case '}': try (DerOutputStream os = new DerOutputStream()) { os.write(DerValue.tag_Sequence, tmp); return os.toByteArray(); } default: type = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_TYPE); if (type.equalsIgnoreCase("integer")) { int num = Integer.parseInt(mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_VALUE)); PutInteger(tmp, num); } else if (type.equalsIgnoreCase("ia5string")) { source = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_SOURCE); value = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_VALUE); if (source.equalsIgnoreCase("file")) PutIA5String(tmp, getFromFile(value)); else PutIA5String(tmp, value); } else if (type.equalsIgnoreCase("octetstring")) { source = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_SOURCE); value = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_VALUE); // It should be colon seperated ASCII Hexdecimal String if (source.equalsIgnoreCase("file")) PutOctetString(tmp, getFromFile(value)); else PutOctetString(tmp, value); } else if (type.equalsIgnoreCase("bmpstring")) { source = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_SOURCE); value = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_VALUE); if (source.equalsIgnoreCase("file")) PutBMPString(tmp, getFromFile(value)); else PutBMPString(tmp, value); } else if (type.equalsIgnoreCase("printablestring")) { source = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_SOURCE); value = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_VALUE); if (source.equalsIgnoreCase("file")) PutPrintableString(tmp, getFromFile(value)); else PutPrintableString(tmp, value); } else if (type.equalsIgnoreCase("visiblestring")) { source = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_SOURCE); value = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_VALUE); if (source.equalsIgnoreCase("file")) PutVisibleString(tmp, getFromFile(value)); else PutVisibleString(tmp, value); } else if (type.equalsIgnoreCase("utctime")) { value = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_VALUE); PutUTCtime(tmp, value); } else if (type.equalsIgnoreCase("oid")) { value = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_VALUE); PutOID(tmp, value); } else if (type.equalsIgnoreCase("boolean")) { boolean bool = false; String b = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_VALUE); if (b.equalsIgnoreCase("true")) bool = true; else bool = false; PutBoolean(tmp, bool); } else if (type.equalsIgnoreCase("null")) { tmp.putNull(); } else { throw new ParseException("Unknown Attribute Type", 0); } } index++; } return tmp.toByteArray(); } /** * Create a GenericASN1Extension with the value and oid. * The criticality is set to false. * * @param name the name of this extension * @param oid the object identifier of this extension * @param pattern to use for encoding this extension * @param critical true if the extension should be treated as critical * @param config additional configuration for this extension */ public GenericASN1Extension(String name, String oid, String pattern, boolean critical, Hashtable config) throws IOException, ParseException { ObjectIdentifier tmpid = new ObjectIdentifier(oid); this.name = name; OID = oid; mConfig = config; this.pattern = pattern; try { if (OIDMap.getName(tmpid) == null) OIDMap.addAttribute("org.mozilla.jss.netscape.security.x509.GenericASN1Extension", oid, name); } catch (CertificateException e) { } this.extensionId = tmpid; this.critical = critical; encodeThis(); } /** * Create a GenericASN1Extension with the value and oid. * The criticality is set to false. * * @param config the values to be set for the extension. */ public GenericASN1Extension(Hashtable config) throws IOException, ParseException { mConfig = config; ObjectIdentifier tmpid = new ObjectIdentifier(mConfig.get(PROP_OID)); name = mConfig.get(PROP_NAME); OID = mConfig.get(PROP_OID); pattern = mConfig.get(PROP_PATTERN); try { if (OIDMap.getName(tmpid) == null) OIDMap.addAttribute("GenericASN1Extension", OID, name); } catch (CertificateException e) { } this.extensionId = tmpid; this.critical = false; String b = mConfig.get(PROP_CRITICAL); if (b.equalsIgnoreCase("true")) this.critical = true; else this.critical = false; encodeThis(); } /** * Create the extension from the passed DER encoded value of the same. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public GenericASN1Extension(Boolean critical, Object value) throws IOException { this.extensionId = new ObjectIdentifier(OID); this.critical = critical.booleanValue(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { throw new IOException("Method not to be called directly."); } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { return null; } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { throw new IOException("Method not to be called directly."); } /** * Returns a printable representation of the GenericASN1Extension. */ @Override public String toString() { return (null); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); try { if (this.extensionValue == null) { this.extensionId = new ObjectIdentifier(OID); this.critical = true; encodeThis(); } } catch (ParseException e) { } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Return the name of this attribute. */ @Override public String getName() { return name; } /** * Set the name of this attribute. */ public void setName(String name) { this.name = name; } /** * Return the OID of this attribute. */ public String getOID() { return OID; } /** * Set the OID of this attribute. */ public void setOID(String oid) { OID = oid; } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement("octet"); return (elements.elements()); } private void PutInteger(DerOutputStream os, int number) throws IOException, ParseException { os.putInteger(new BigInt(number)); return; } private void PutIA5String(DerOutputStream os, String value) throws IOException, ParseException { os.putIA5String(value); return; } private void PutOctetString(DerOutputStream os, String value) throws IOException, ParseException { StringTokenizer token = new StringTokenizer(value, ":"); byte[] octets = new byte[token.countTokens()]; for (int i = 0; token.hasMoreElements(); i++) { String num = (String) token.nextElement(); octets[i] = (byte) Integer.parseInt(num, 16); } os.putOctetString(octets); return; } private void PutBMPString(DerOutputStream os, String value) throws IOException, ParseException { os.putBMPString(value); return; } private void PutPrintableString(DerOutputStream os, String value) throws IOException, ParseException { os.putPrintableString(value); return; } private void PutVisibleString(DerOutputStream os, String value) throws IOException, ParseException { os.putVisibleString(value); return; } private void PutUTCtime(DerOutputStream os, String value) throws IOException, ParseException { DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT); os.putUTCTime(df.parse(value)); return; } private void PutOID(DerOutputStream os, String value) throws IOException, ParseException { os.putOID(new ObjectIdentifier(value)); return; } private void PutBoolean(DerOutputStream os, boolean value) throws IOException, ParseException { os.putBoolean(value); return; } private String getFromFile(String fname) throws IOException { String s = null; byte[] buff = null; int i = 0; int j = 0; if ((fname == null) || (fname.equals(""))) { throw new IOException("File name is not provided."); } FileInputStream fis = null; try { fis = new FileInputStream(fname); int n = 0; while ((n = fis.available()) > 0) { buff = new byte[n]; int result = fis.read(buff); if (result == -1) break; s = new String(buff); } } finally { if (fis != null) { fis.close(); } } if (s == null) { return ""; } for (i = 0, j = 0; j < s.length(); j++) { int ch = s.charAt(j); if (ch == 10 || ch == 13 || ch == 9) continue; i++; } buff = new byte[i]; for (i = 0, j = 0; j < s.length(); j++) { int ch = s.charAt(j); if (ch == 10 || ch == 13 || ch == 9) continue; buff[i++] = (byte) ch; } s = new String(buff); return s; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/extensions/InhibitAnyPolicyExtension.java000066400000000000000000000126541412550063600336440ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.extensions; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.security.cert.CertificateException; import java.util.Enumeration; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; import org.mozilla.jss.netscape.security.x509.CertAttrSet; import org.mozilla.jss.netscape.security.x509.Extension; import org.mozilla.jss.netscape.security.x509.OIDMap; /** * RFC3280: * * id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } * * InhibitAnyPolicy ::= SkipCerts * * SkipCerts ::= INTEGER (0..MAX) */ public class InhibitAnyPolicyExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -8963439897419343166L; public static final String OID = "2.5.29.54"; public static final String NAME = OIDMap.EXT_INHIBIT_ANY_POLICY_NAME; private BigInt mSkipCerts = new BigInt(-1); static { try { OIDMap.addAttribute(InhibitAnyPolicyExtension.class.getName(), OID, NAME); } catch (CertificateException e) { } } public InhibitAnyPolicyExtension() throws IOException { this(false, null); } public InhibitAnyPolicyExtension(boolean crit, BigInt skipCerts) throws IOException { try { extensionId = ObjectIdentifier.getObjectIdentifier(OID); } catch (IOException e) { // never here } critical = crit; mSkipCerts = skipCerts; encodeExtValue(); } public InhibitAnyPolicyExtension(Boolean crit, Object value) throws IOException { extensionId = ObjectIdentifier.getObjectIdentifier(OID); critical = crit.booleanValue(); //extensionValue = (byte[]) ((byte[]) byteVal).clone(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } extensionValue = extValue; decodeThis(); } @Override public void setCritical(boolean newValue) { if (critical != newValue) { critical = newValue; } } public BigInt getSkipCerts() { return mSkipCerts; } @Override public String toString() { String presentation = "ObjectId: " + OID + " "; if (critical) { presentation += "Criticality=true"; } else { presentation += "Criticality=false"; } if (extensionValue != null) { String extByteValue = " skipCerts=" + mSkipCerts; presentation += extByteValue; } return presentation; } @Override public void decode(InputStream in) throws CertificateException, IOException { } @Override public void set(String name, Object obj) throws CertificateException, IOException { // NOT USED } @Override public Object get(String name) throws CertificateException, IOException { // NOT USED return null; } @Override public Enumeration getAttributeNames() { return null; } @Override public String getName() { return NAME; } @Override public void delete(String name) throws CertificateException, IOException { // NOT USED } private void decodeThis() throws IOException { DerValue val = new DerValue(this.extensionValue); mSkipCerts = val.getInteger(); } @Override public void encode(OutputStream out) throws IOException { try (DerOutputStream os = new DerOutputStream()) { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { try { extensionId = ObjectIdentifier.getObjectIdentifier(OID); } catch (IOException e) { // never here } os.putInteger(mSkipCerts); this.extensionValue = os.toByteArray(); } super.encode(tmp); out.write(tmp.toByteArray()); } } private void encodeExtValue() throws IOException { DerOutputStream out = new DerOutputStream(); try { out.putInteger(mSkipCerts); } catch (IOException e) { } finally { out.close(); } extensionValue = out.toByteArray(); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/extensions/KerberosName.java000066400000000000000000000114051412550063600310770ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.extensions; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Vector; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** * This represents a KerberosName as defined in * RFC 1510. * * KerberosName ::= SEQUENCE { * realm [0] Realm, * principalName [1] CertPrincipalName -- defined above * } * * CertPrincipalName ::= SEQUENCE { * name-type[0] INTEGER, * name-string[1] SEQUENCE OF UTF8String * } * * @author thomask * @version $Revision$, $Date$ */ public class KerberosName { public static final int OID[] = { 1, 3, 6, 1, 5, 2, 2 }; public static final ObjectIdentifier KRB5_PRINCIPAL_NAME = new ObjectIdentifier(OID); private String m_realm = null; private int m_name_type = 0; private Vector m_name_strings = null; public KerberosName(String realm, int name_type, Vector name_strings) { m_realm = realm; m_name_type = name_type; m_name_strings = name_strings; } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors. */ public void encode(OutputStream out) throws IOException { try (DerOutputStream seq = new DerOutputStream()) { DerOutputStream tmp = new DerOutputStream(); DerOutputStream realm = new DerOutputStream(); realm.putGeneralString(m_realm); tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0), realm); DerOutputStream seq1 = new DerOutputStream(); DerOutputStream tmp1 = new DerOutputStream(); DerOutputStream name_type = new DerOutputStream(); name_type.putInteger(new BigInt(m_name_type)); tmp1.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0), name_type); DerOutputStream name_strings = new DerOutputStream(); DerOutputStream name_string = new DerOutputStream(); for (int i = 0; i < m_name_strings.size(); i++) { name_string.putGeneralString(m_name_strings.elementAt(i)); } name_strings.write(DerValue.tag_SequenceOf, name_string); tmp1.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 1), name_strings); seq1.write(DerValue.tag_Sequence, tmp1); tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 1), seq1); seq.write(DerValue.tag_Sequence, tmp); out.write(seq.toByteArray()); } } public byte[] toByteArray() throws IOException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); encode(bos); return bos.toByteArray(); } @Override public String toString() { String strings = null; for (int i = 0; i < m_name_strings.size(); i++) { if (strings == null) { strings = m_name_strings.elementAt(i); } else { strings += ","; strings += m_name_strings.elementAt(i); } } return "Realm: " + m_realm + " Name Type: " + m_name_type + " Name String(s):" + strings; } public static void main(String[] argv) { Vector strings = new Vector(); strings.addElement("name"); KerberosName k = new KerberosName("realm", 0, strings); System.out.println(k.toString()); try { FileOutputStream os = new FileOutputStream("/tmp/out.der"); k.encode(os); os.close(); } catch (Exception e) { System.out.println(e.toString()); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/extensions/NSCertTypeExtension.java000066400000000000000000000265021412550063600324230ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.extensions; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.BitArray; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; import org.mozilla.jss.netscape.security.x509.CertAttrSet; import org.mozilla.jss.netscape.security.x509.Extension; /** * NSCertTypeExtension * Represents Netscape Certificate Type Extension * *

* This deprecated extension, if present, defines both the purpose (e.g., encipherment, signature, certificate signing) * and the application (e.g., SSL, S/Mime or Object Signing of the key contained in the certificate. * * @author galperin * @version $Revision$, $Date$ */ public class NSCertTypeExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 1856407688086284397L; // The object identifiers private static final int CertType_data[] = { 2, 16, 840, 1, 113730, 1, 1 }; /** * Identifies the particular public key used to sign the certificate. */ public static final ObjectIdentifier CertType_Id = new ObjectIdentifier(CertType_data); /** * Attribute names. */ public static final String NAME = "NSCertType"; public static final String SSL_CLIENT = "ssl_client"; public static final String SSL_SERVER = "ssl_server"; public static final String EMAIL = "email"; public static final String OBJECT_SIGNING = "object_signing"; public static final String SSL_CA = "ssl_ca"; public static final String EMAIL_CA = "email_ca"; public static final String OBJECT_SIGNING_CA = "object_signing_ca"; /** * Attribute names. */ public static final int SSL_CLIENT_BIT = 0; public static final int SSL_SERVER_BIT = 1; public static final int EMAIL_BIT = 2; public static final int OBJECT_SIGNING_BIT = 3; // 4 is reserved. public static final int SSL_CA_BIT = 5; public static final int EMAIL_CA_BIT = 6; public static final int OBJECT_SIGNING_CA_BIT = 7; public static final int NBITS = 8; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.NSCertType"; // Private data members private byte[] mBitString; private static class MapEntry { String mName; int mPosition; MapEntry(String name, int position) { mName = name; mPosition = position; } } private static MapEntry[] mMapData = { new MapEntry(SSL_CLIENT, 0), new MapEntry(SSL_SERVER, 1), new MapEntry(EMAIL, 2), new MapEntry(OBJECT_SIGNING, 3), // note that bit 4 is reserved new MapEntry(SSL_CA, 5), new MapEntry(EMAIL_CA, 6), new MapEntry(OBJECT_SIGNING_CA, 7), }; private static Vector mAttributeNames = new Vector(); static { for (int i = 0; i < mMapData.length; ++i) { mAttributeNames.addElement(mMapData[i].mName); } } private static int getPosition(String name) throws CertificateException { for (int i = 0; i < mMapData.length; ++i) { if (name.equalsIgnoreCase(mMapData[i].mName)) return mMapData[i].mPosition; } throw new CertificateException("Attribute name [" + name + "] not recognized by" + " CertAttrSet:NSCertType."); } // Encode this extension value private void encodeThis() throws IOException { try (DerOutputStream os = new DerOutputStream()) { os.putUnalignedBitString(mBitString); this.extensionValue = os.toByteArray(); } } /** * Check if bit is set. * * @param position the position in the bit string to check. */ public boolean isSet(int position) { int index = position / 8; byte pos = (byte) (1 << (7 - (position % 8))); if (mBitString.length <= index) return false; return ((mBitString[index] & pos) != 0); } /** * Set the bit at the specified position. */ public void set(int position, boolean val) { int index = position / 8; byte pos = (byte) (1 << (7 - (position % 8))); if (index >= mBitString.length) { byte[] tmp = new byte[index + 1]; System.arraycopy(mBitString, 0, tmp, 0, mBitString.length); mBitString = tmp; } if (val) { mBitString[index] |= pos; } else { mBitString[index] &= ~pos; } } /** * Create NSCertTypeExtension from boolean array. * The criticality is set to false. */ public NSCertTypeExtension(boolean critical, boolean[] bits) { this.extensionId = CertType_Id; this.critical = critical; this.mBitString = new byte[0]; for (int i = 0; i < bits.length && i < 8; i++) { set(i, bits[i]); } } public NSCertTypeExtension(boolean[] bits) { this.extensionId = CertType_Id; this.critical = false; this.mBitString = new byte[0]; for (int i = 0; i < bits.length && i < 8; i++) { set(i, bits[i]); } } /** * Create a NSCertTypeExtension with the passed bit settings. * The criticality is set to false. * * @param bitString the bits to be set for the extension. */ public NSCertTypeExtension(boolean critical, byte[] bitString) throws IOException { this.mBitString = bitString; this.extensionId = CertType_Id; this.critical = critical; encodeThis(); } public NSCertTypeExtension(byte[] bitString) throws IOException { this.mBitString = bitString; this.extensionId = CertType_Id; this.critical = false; encodeThis(); } /** * Create the extension from the passed DER encoded value of the same. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public NSCertTypeExtension(Boolean critical, Object value) throws IOException { /** * logger.trace("NSCertTypeExtension"); * this.mBitString = new byte[1]; * this.mBitString[0] = (byte)0x00; * return; **/ this.extensionId = CertType_Id; this.critical = critical.booleanValue(); byte[] extValue = ((byte[]) value).clone(); this.extensionValue = extValue; DerValue val = new DerValue(extValue); BitArray bitArray = val.getUnalignedBitString(); if (bitArray == null) { throw new IOException("Invalid Encoded DER Value"); } this.mBitString = bitArray.toByteArray(); } /** * Create a default key usage. */ public NSCertTypeExtension() { this.extensionId = CertType_Id; this.critical = false; this.mBitString = new byte[0]; try { encodeThis(); } catch (Exception e) { } } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws CertificateException { if (!(obj instanceof Boolean)) { throw new CertificateException("Attribute must be of type Boolean."); } boolean val = ((Boolean) obj).booleanValue(); set(getPosition(name), val); } /** * Get the attribute value. */ @Override public Object get(String name) throws CertificateException { return Boolean.valueOf(isSet(getPosition(name))); } /** * Delete the attribute value. */ @Override public void delete(String name) throws CertificateException { set(getPosition(name), false); } /** * Returns a printable representation of the NSCertType. */ @Override public String toString() { String s = super.toString() + "NSCertType [\n"; try { if (isSet(getPosition(SSL_CLIENT))) { s += " SSL client"; } if (isSet(getPosition(SSL_SERVER))) { s += " SSL server"; } if (isSet(getPosition(EMAIL))) { s += " Email"; } if (isSet(getPosition(OBJECT_SIGNING))) { s += " Object Signing"; } if (isSet(getPosition(SSL_CA))) { s += " SSL CA"; } if (isSet(getPosition(EMAIL_CA))) { s += " Email CA"; } if (isSet(getPosition(OBJECT_SIGNING_CA))) { s += " Object Signing CA"; } } catch (Exception e) { // this is reached only if there is a bug throw new IllegalArgumentException(e.getMessage()); } s += "]\n"; return (s); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); encodeThis(); if (this.extensionValue == null) { this.extensionId = CertType_Id; this.critical = true; } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { return mAttributeNames.elements(); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } public static void main(String[] argv) { } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/extensions/OCSPNoCheckExtension.java000066400000000000000000000111671412550063600324230ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.extensions; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Enumeration; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; import org.mozilla.jss.netscape.security.x509.CertAttrSet; import org.mozilla.jss.netscape.security.x509.Extension; import org.mozilla.jss.netscape.security.x509.OIDMap; /** * This represents the OCSPNoCheck extension. */ public class OCSPNoCheckExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -4692759557964594790L; public static final String OID = "1.3.6.1.5.5.7.48.1.5"; public static final String NAME = "OCSPNoCheckExtension"; private byte mCached[] = null; static { try { OIDMap.addAttribute(OCSPNoCheckExtension.class.getName(), OID, NAME); } catch (CertificateException e) { } } public OCSPNoCheckExtension() throws IOException { this(Boolean.FALSE); } public OCSPNoCheckExtension(Boolean crit) throws IOException { try { extensionId = ObjectIdentifier.getObjectIdentifier(OCSPNoCheckExtension.OID); } catch (IOException e) { // never here } critical = crit.booleanValue(); DerOutputStream tmpD = new DerOutputStream(); try { tmpD.putNull(); } catch (IOException ex) { } finally { tmpD.close(); } extensionValue = tmpD.toByteArray(); } public OCSPNoCheckExtension(Boolean crit, Object byteVal) { try { extensionId = ObjectIdentifier.getObjectIdentifier(OCSPNoCheckExtension.OID); } catch (IOException e) { // never here } critical = crit.booleanValue(); extensionValue = ((byte[]) byteVal).clone(); } @Override public void setCritical(boolean newValue) { if (critical != newValue) { critical = newValue; mCached = null; } } @Override public void encode(DerOutputStream out) throws IOException { if (mCached == null) { super.encode(out); mCached = out.toByteArray(); } } @Override public String toString() { String presentation = "oid=" + OID + " "; if (critical) { presentation += "critical=true"; } if (extensionValue != null) { StringBuffer extByteValue = new StringBuffer(" val="); for (int i = 0; i < extensionValue.length; i++) { extByteValue.append(extensionValue[i] + " "); } presentation += extByteValue.toString(); } return presentation; } @Override public void decode(InputStream in) throws CertificateException, IOException { // NOT USED } @Override public void encode(OutputStream out) throws CertificateException, IOException { if (mCached == null) { DerOutputStream temp = new DerOutputStream(); encode(temp); } out.write(mCached); } @Override public void set(String name, Object obj) throws CertificateException, IOException { // NOT USED } @Override public Object get(String name) throws CertificateException, IOException { // NOT USED return null; } @Override public Enumeration getAttributeNames() { // NOT USED return null; } @Override public String getName() { return NAME; } @Override public void delete(String name) throws CertificateException, IOException { // NOT USED } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/extensions/PresenceServerExtension.java000066400000000000000000000246351412550063600333630ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.extensions; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Enumeration; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; import org.mozilla.jss.netscape.security.x509.CertAttrSet; import org.mozilla.jss.netscape.security.x509.Extension; public class PresenceServerExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -6333109673043357921L; private boolean mCritical; private int mVersion = 0; private String mStreetAddress = null; private String mTelephoneNumber = null; private String mRFC822Name = null; private String mID = null; private String mHostName = null; private int mPortNumber = 0; private int mMaxUsers = 0; private int mServiceLevel = 0; public static final String OID = "2.16.840.1.113730.1.18"; /* public PresenceServerExtension() { } */ public PresenceServerExtension(Boolean critical, Object value) throws IOException { this.extensionId = new ObjectIdentifier(OID); this.critical = critical.booleanValue(); this.extensionValue = ((byte[]) value).clone(); decodeThis(); } public PresenceServerExtension( boolean critical, int version, String streetAddress, String telephoneNumber, String rfc822Name, String ID, String hostName, int portNumber, int maxUsers, int serviceLevel) throws IOException { mCritical = critical; mVersion = version; mStreetAddress = streetAddress; mTelephoneNumber = telephoneNumber; mRFC822Name = rfc822Name; mID = ID; mHostName = hostName; mPortNumber = portNumber; mMaxUsers = maxUsers; mServiceLevel = serviceLevel; this.extensionId = new ObjectIdentifier(OID); this.critical = mCritical; encodeThis(); } public int getVersion() { return mVersion; } public String getStreetAddress() { return mStreetAddress; } public String getTelephoneNumber() { return mTelephoneNumber; } public String getRFC822() { return mRFC822Name; } public String getID() { return mID; } public String getHostName() { return mHostName; } public int getPortNumber() { return mPortNumber; } public int getMaxUsers() { return mMaxUsers; } public int getServiceLevel() { return mServiceLevel; } public void encodeThis() throws IOException { try (DerOutputStream out = new DerOutputStream()) { DerOutputStream temp = new DerOutputStream(); temp.putInteger(new BigInt(mVersion)); temp.putOctetString(mStreetAddress.getBytes()); temp.putOctetString(mTelephoneNumber.getBytes()); temp.putOctetString(mRFC822Name.getBytes()); temp.putOctetString(mID.getBytes()); temp.putOctetString(mHostName.getBytes()); temp.putInteger(new BigInt(mPortNumber)); temp.putInteger(new BigInt(mMaxUsers)); temp.putInteger(new BigInt(mServiceLevel)); out.write(DerValue.tag_Sequence, temp); this.extensionValue = out.toByteArray(); } } public void decodeThis() throws IOException { DerInputStream val = new DerInputStream(this.extensionValue); byte data[] = null; DerValue seq[] = val.getSequence(0); mVersion = seq[0].getInteger().toInt(); data = null; if (seq[1].length() > 0) { data = seq[1].getOctetString(); } if (data == null) { mStreetAddress = ""; } else { mStreetAddress = new String(data); } data = null; if (seq[2].length() > 0) data = seq[2].getOctetString(); if (data == null) { mTelephoneNumber = ""; } else { mTelephoneNumber = new String(data); } data = null; if (seq[3].length() > 0) data = seq[3].getOctetString(); if (data == null) { mRFC822Name = ""; } else { mRFC822Name = new String(data); } data = null; if (seq[4].length() > 0) data = seq[4].getOctetString(); if (data == null) { mID = ""; } else { mID = new String(data); } data = null; if (seq[5].length() > 0) data = seq[5].getOctetString(); if (data == null) { mHostName = ""; } else { mHostName = new String(data); } mPortNumber = seq[6].getInteger().toInt(); mMaxUsers = seq[7].getInteger().toInt(); mServiceLevel = seq[8].getInteger().toInt(); } @Override public void decode(InputStream in) throws CertificateException, IOException { } @Override public void encode(OutputStream out) throws CertificateException, IOException { DerOutputStream dos = new DerOutputStream(); super.encode(dos); out.write(dos.toByteArray()); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { throw new IOException("Method not to be called directly."); } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { return null; } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { throw new IOException("Method not to be called directly."); } @Override public Enumeration getAttributeNames() { return null; } /** * Return the name of this attribute. */ @Override public String getName() { return "PresenceServerExtension"; } /** * Set the name of this attribute. */ public void setName(String name) { } /** * Return the OID of this attribute. */ public String getOID() { return OID; } /** * Set the OID of this attribute. */ public void setOID(String oid) { } public static void main(String args[]) { /* 0 30 115: SEQUENCE { 2 06 9: OBJECT IDENTIFIER '2 16 840 1 113730 1 100' 13 04 102: OCTET STRING, encapsulates { 15 30 100: SEQUENCE { 17 02 1: INTEGER 0 20 04 31: OCTET STRING : 34 30 31 45 20 4D 69 64 64 6C 65 66 69 65 6C 64 : 20 52 64 2E 2C 4D 56 2C 43 41 39 34 30 34 31 53 04 12: OCTET STRING : 36 35 30 2D 31 31 31 2D 31 31 31 31 67 04 18: OCTET STRING : 61 64 6D 69 6E 40 6E 65 74 73 63 61 70 65 2E 63 : 6F 6D 87 04 10: OCTET STRING : 70 73 2D 63 61 70 69 74 6F 6C 99 04 7: OCTET STRING : 63 61 70 69 74 6F 6C 108 02 1: INTEGER 80 111 02 1: INTEGER 10 114 02 1: INTEGER 1 : } : } : } */ ByteArrayOutputStream dos = null; FileOutputStream fos = null; try { boolean critical = false; int version = 1; String streetAddress = "401E Middlefield Rd.,MV,CA94041"; String telephoneNumber = "650-111-1111"; String rfc822Name = "admin@netscape.com"; String ID = "ps-capitol"; String hostName = "capitol"; int portNumber = 80; int maxUsers = 10; int serviceLevel = 1; PresenceServerExtension ext = new PresenceServerExtension( critical, version, streetAddress, telephoneNumber, rfc822Name, ID, hostName, portNumber, maxUsers, serviceLevel); // encode dos = new ByteArrayOutputStream(); ext.encode(dos); fos = new FileOutputStream("pse.der"); fos.write(dos.toByteArray()); Extension ext1 = new Extension(new DerValue(dos.toByteArray())); @SuppressWarnings("unused") PresenceServerExtension ext2 = new PresenceServerExtension( Boolean.valueOf(false), ext1.getExtensionValue()); } catch (IOException e) { e.printStackTrace(); } catch (CertificateException e) { e.printStackTrace(); } finally { if (dos != null) { try { dos.close(); } catch (IOException e) { e.printStackTrace(); } } if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/extensions/SubjectInfoAccessExtension.java000066400000000000000000000205501412550063600337550ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.extensions; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; import org.mozilla.jss.netscape.security.util.Utils; import org.mozilla.jss.netscape.security.x509.CertAttrSet; import org.mozilla.jss.netscape.security.x509.Extension; import org.mozilla.jss.netscape.security.x509.GeneralName; import org.mozilla.jss.netscape.security.x509.URIName; /** * This represents the subject information access extension * as defined in RFC3280. * * @author thomask * @version $Revision$, $Date$ */ public class SubjectInfoAccessExtension extends Extension implements CertAttrSet { private static final long serialVersionUID = 7237321566602583325L; public static final String NAME = "SubjectInfoAccessExtension"; public static final int OID_OCSP[] = { 1, 3, 6, 1, 5, 5, 7, 48, 1 }; public static final ObjectIdentifier METHOD_OCSP = new ObjectIdentifier(OID_OCSP); public static final int OID_CA_ISSUERS[] = { 1, 3, 6, 1, 5, 5, 7, 48, 2 }; public static final ObjectIdentifier METHOD_CA_ISSUERS = new ObjectIdentifier(OID_CA_ISSUERS); public static final int OID[] = { 1, 3, 6, 1, 5, 5, 7, 1, 11 }; public static final ObjectIdentifier ID = new ObjectIdentifier(OID); private Vector mDesc = new Vector(); /** * Create the extension from the passed DER encoded value of the same. * * @param critical true if the extension is to be treated as critical. */ public SubjectInfoAccessExtension(boolean critical) { this.extensionId = ID; this.critical = critical; this.extensionValue = null; // build this when encodeThis() is called } /** * Create the extension from the passed DER encoded value of the same. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public SubjectInfoAccessExtension(Boolean critical, Object value) throws IOException { this.extensionId = ID; this.critical = critical.booleanValue(); this.extensionValue = ((byte[]) value).clone(); decodeThis(); } /** * Sets extension attribute. */ @Override public void set(String name, Object obj) throws CertificateException { // NOT USED } /** * Retrieves extension attribute. */ @Override public Object get(String name) throws CertificateException { // NOT USED return null; } /** * Deletes attribute. */ @Override public void delete(String name) throws CertificateException { // NOT USED } /** * Decodes this extension. */ @Override public void decode(InputStream in) throws IOException { // NOT USED } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { // NOT USED return null; } /** * Return the name of this attribute. */ @Override public String getName() { return NAME; } /** * Adds Access Description. */ public void addAccessDescription( ObjectIdentifier method, GeneralName gn) { clearValue(); mDesc.addElement(new AccessDescription(method, gn)); } public AccessDescription getAccessDescription(int pos) { return mDesc.elementAt(pos); } /** * Returns the number of access description. */ public int numberOfAccessDescription() { return mDesc.size(); } private void decodeThis() throws IOException { DerValue val = new DerValue(this.extensionValue); if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding of AuthInfoAccess extension"); } while (val.data.available() != 0) { DerValue seq = val.data.getDerValue(); ObjectIdentifier method = seq.data.getDerValue().getOID(); GeneralName gn = new GeneralName(seq.data.getDerValue()); addAccessDescription(method, gn); } } private void encodeThis() throws IOException { try (DerOutputStream seq = new DerOutputStream(); DerOutputStream tmp = new DerOutputStream()) { for (int i = 0; i < mDesc.size(); i++) { DerOutputStream tmp0 = new DerOutputStream(); AccessDescription ad = mDesc.elementAt(i); tmp0.putOID(ad.getMethod()); ad.getLocation().encode(tmp0); tmp.write(DerValue.tag_Sequence, tmp0); } seq.write(DerValue.tag_Sequence, tmp); this.extensionValue = seq.toByteArray(); } } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Returns a printable representation of the AuthInfoAccess. */ @Override public String toString() { StringBuffer s=new StringBuffer(super.toString() + "AuthInfoAccess [\n"); for (int i = 0; i < mDesc.size(); i++) { AccessDescription ad = mDesc.elementAt(i); s.append( "(" + i + ")"); s.append(" "); s.append(ad.getMethod().toString() + " " + ad.getLocation().toString()); } return (s.toString() + "]\n"); } public static void main(String[] argv) { AuthInfoAccessExtension aia = new AuthInfoAccessExtension(false); GeneralName ocspName = new GeneralName(new URIName("http://ocsp.netscape.com")); aia.addAccessDescription(METHOD_OCSP, ocspName); GeneralName caIssuersName = new GeneralName(new URIName("http://ocsp.netscape.com")); aia.addAccessDescription(METHOD_CA_ISSUERS, caIssuersName); ByteArrayOutputStream os = new ByteArrayOutputStream(); try { aia.encode(os); System.out.println(Utils.base64encode(os.toByteArray(), true)); } catch (IOException e) { System.out.println(e.toString()); } try { // test serialization ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(aia); ByteArrayInputStream bis = new ByteArrayInputStream( bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); AuthInfoAccessExtension clone = (AuthInfoAccessExtension) ois.readObject(); System.out.println(clone); } catch (Exception e) { System.out.println(e.toString()); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/pkcs/000077500000000000000000000000001412550063600244175ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/pkcs/ContentInfo.java000066400000000000000000000122541412550063600275140ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.pkcs; import java.io.IOException; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** * A ContentInfo type, as defined in PKCS#7. * * @version 1.12 * @author Benjamin Renaud */ public class ContentInfo { // pkcs7 pre-defined content types private static int[] pkcs7 = { 1, 2, 840, 113549, 1, 7 }; private static int[] data = { 1, 2, 840, 113549, 1, 7, 1 }; private static int[] sdata = { 1, 2, 840, 113549, 1, 7, 2 }; private static int[] edata = { 1, 2, 840, 113549, 1, 7, 3 }; private static int[] sedata = { 1, 2, 840, 113549, 1, 7, 4 }; private static int[] ddata = { 1, 2, 840, 113549, 1, 7, 5 }; private static int[] crdata = { 1, 2, 840, 113549, 1, 7, 6 }; public static final ObjectIdentifier PKCS7_OID = new ObjectIdentifier(pkcs7); public static final ObjectIdentifier DATA_OID = new ObjectIdentifier(data); public static final ObjectIdentifier SIGNED_DATA_OID = new ObjectIdentifier(sdata); public static final ObjectIdentifier ENVELOPED_DATA_OID = new ObjectIdentifier(edata); public static final ObjectIdentifier SIGNED_AND_ENVELOPED_DATA_OID = new ObjectIdentifier(sedata); public static final ObjectIdentifier DIGESTED_DATA_OID = new ObjectIdentifier(ddata); public static final ObjectIdentifier ENCRYPTED_DATA_OID = new ObjectIdentifier(crdata); ObjectIdentifier contentType; DerValue content; // OPTIONAL public ContentInfo(ObjectIdentifier contentType, DerValue content) { this.contentType = contentType; this.content = content; } /** * Make a contentInfo of type data. */ public ContentInfo(byte[] bytes) { DerValue octetString = new DerValue(DerValue.tag_OctetString, bytes); this.contentType = DATA_OID; this.content = octetString; } public ContentInfo(DerInputStream derin) throws IOException, ParsingException { DerInputStream disType; DerInputStream disTaggedContent; DerValue type; DerValue taggedContent; DerValue[] typeAndContent; DerValue[] contents; typeAndContent = derin.getSequence(2); // Parse the content type type = typeAndContent[0]; disType = new DerInputStream(type.toByteArray()); contentType = disType.getOID(); // Parse the content (OPTIONAL field). // Skip the [0] EXPLICIT tag by pretending that the content is the one // and only element in an implicitly tagged set if (typeAndContent.length > 1) { // content is OPTIONAL taggedContent = typeAndContent[1]; disTaggedContent = new DerInputStream(taggedContent.toByteArray()); contents = disTaggedContent.getSet(1, true); content = contents[0]; } } public DerValue getContent() { return content; } public byte[] getData() throws IOException { if (contentType.equals(DATA_OID)) { return content.getOctetString(); } throw new IOException("content type is not DATA: " + contentType); } public void encode(DerOutputStream out) throws IOException { DerOutputStream contentDerCode; DerOutputStream seq; DerValue taggedContent; contentDerCode = new DerOutputStream(); content.encode(contentDerCode); // Add the [0] EXPLICIT tag in front of the content encoding taggedContent = new DerValue((byte) 0xA0, contentDerCode.toByteArray()); seq = new DerOutputStream(); seq.putOID(contentType); seq.putDerValue(taggedContent); out.write(DerValue.tag_Sequence, seq); } /** * Returns a byte array representation of the data held in * the content field. */ public byte[] getContentBytes() throws IOException { DerInputStream dis = new DerInputStream(content.toByteArray()); return dis.getOctetString(); } @Override public String toString() { String out = ""; out += "Content Info Sequence\n\tContent type: " + contentType + "\n"; out += "\tContent: " + content; return out; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/pkcs/EncodingException.java000066400000000000000000000025651412550063600306770ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.pkcs; public class EncodingException extends Exception { /** * */ private static final long serialVersionUID = -6126764125859196917L; public EncodingException() { super(); } public EncodingException(String mesg) { super(mesg); } public EncodingException(String mesg, Throwable cause) { super(mesg, cause); } public EncodingException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(mesg, cause, enableSuppression, writableStackTrace); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS10.java000066400000000000000000000321241412550063600261650ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.pkcs; import java.io.IOException; import java.io.PrintStream; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.security.cert.CertificateException; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.Cert; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.Utils; import org.mozilla.jss.netscape.security.x509.AlgorithmId; import org.mozilla.jss.netscape.security.x509.X500Name; import org.mozilla.jss.netscape.security.x509.X500Signer; import org.mozilla.jss.netscape.security.x509.X509Key; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * PKCS #10 certificate requests are created and sent to Certificate * Authorities, which then create X.509 certificates and return them to * the entity which created the certificate request. These cert requests * basically consist of the subject's X.500 name and public key, signed * using the corresponding private key. * * The ASN.1 syntax for a Certification Request is: * *

 * CertificationRequest ::= SEQUENCE {
 *    certificationRequestInfo CertificationRequestInfo,
 *    signatureAlgorithm       SignatureAlgorithmIdentifier,
 *    signature                Signature
 *  }
 *
 * SignatureAlgorithmIdentifier ::= AlgorithmIdentifier
 * Signature ::= BIT STRING
 *
 * CertificationRequestInfo ::= SEQUENCE {
 *    version                 Version,
 *    subject                 Name,
 *    subjectPublicKeyInfo    SubjectPublicKeyInfo,
 *    attributes [0] IMPLICIT Attributes
 * }
 * Attributes ::= SET OF Attribute
 * 
* * @author David Brownell * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.28 */ public class PKCS10 { public static Logger logger = LoggerFactory.getLogger(PKCS10.class); /** * Constructs an unsigned PKCS #10 certificate request. Before this * request may be used, it must be encoded and signed. Then it * must be retrieved in some conventional format (e.g. string). * * @param publicKey the public key that should be placed * into the certificate generated by the CA. */ public PKCS10(X509Key publicKey) { subjectPublicKeyInfo = publicKey; attributeSet = new PKCS10Attributes(); } /** * Constructs an unsigned PKCS #10 certificate request. Before this * request may be used, it must be encoded and signed. Then it * must be retrieved in some conventional format (e.g. string). * * @param publicKey the public key that should be placed * into the certificate generated by the CA. * @param attributes additonal set of PKCS10 attributes requested * for in the certificate. */ public PKCS10(X509Key publicKey, PKCS10Attributes attributes) { subjectPublicKeyInfo = publicKey; if (attributes != null) attributeSet = attributes; else attributeSet = new PKCS10Attributes(); } /** * Parses an encoded, signed PKCS #10 certificate request, verifying * the request's signature as it does so. This constructor would * typically be used by a Certificate Authority, from which a new * certificate would then be constructed. * * @param data the DER-encoded PKCS #10 request. * @param sigver boolean specifies signature verification enabled or not * @exception IOException for low level errors reading the data * @exception SignatureException when the signature is invalid * @exception NoSuchAlgorithmException when the signature * algorithm is not supported in this environment */ public PKCS10(byte data[], boolean sigver) throws IOException, SignatureException, NoSuchAlgorithmException, java.security.NoSuchProviderException { DerInputStream in; DerValue seq[]; AlgorithmId id; byte sigData[]; Signature sig; String msg = ""; logger.debug("PKCS10: begins"); if (data == null) { throw new IllegalArgumentException("Missing PKCS #10 data"); } certificateRequest = data; // // Outer sequence: request, signature algorithm, signature. // Parse, and prepare to verify later. // in = new DerInputStream(data); seq = in.getSequence(3); if (seq == null) { throw new IllegalArgumentException("in.getSequence null"); } if (seq.length != 3) { throw new IllegalArgumentException("Invalid PKCS #10 request"); } data = seq[0].toByteArray(); // reusing this variable certRequestInfo = seq[0].toByteArray(); // make a copy id = AlgorithmId.parse(seq[1]); sigData = seq[2].getBitString(); // // Inner sequence: version, name, key, attributes // @SuppressWarnings("unused") BigInt serial = seq[0].data.getInteger(); // consume serial /* if (serial.toInt () != 0) throw new IllegalArgumentException ("not PKCS #10 v1"); */ subject = new X500Name(seq[0].data); msg = "Request Subject: " + subject + ": "; byte val1[] = seq[0].data.getDerValue().toByteArray(); subjectPublicKeyInfo = X509Key.parse(new DerValue(val1)); PublicKey publicKey = X509Key.parsePublicKey(new DerValue(val1)); if (publicKey == null) { logger.error("PKCS10: " + msg + "publicKey null"); throw new SignatureException(msg + "publicKey null"); } // Cope with a somewhat common illegal PKCS #10 format if (seq[0].data.available() != 0) { attributeSet = new PKCS10Attributes(seq[0].data); } else { attributeSet = new PKCS10Attributes(); } // // OK, we parsed it all ... validate the signature using the // key and signature algorithm we found. // temporary commented out try { String idName = id.getName(); if (idName.equals("MD5withRSA")) idName = "MD5/RSA"; else if (idName.equals("MD2withRSA")) idName = "MD2/RSA"; else if (idName.equals("SHA1withRSA")) idName = "SHA1/RSA"; else if (idName.equals("SHA1withDSA")) idName = "SHA1/DSA"; else if (idName.equals("SHA256withRSA")) idName = "SHA256/RSA"; else if (idName.equals("SHA384withRSA")) idName = "SHA384/RSA"; else if (idName.equals("SHA512withRSA")) idName = "SHA512/RSA"; else if (idName.equals("SHA1withEC")) idName = "SHA1/EC"; else if (idName.equals("SHA256withEC")) idName = "SHA256/EC"; else if (idName.equals("SHA384withEC")) idName = "SHA384/EC"; else if (idName.equals("SHA512withEC")) idName = "SHA512/EC"; if (sigver) { sig = Signature.getInstance(idName, "Mozilla-JSS"); sig.initVerify(publicKey); sig.update(data); if (!sig.verify(sigData)) { logger.error("PKCS10: " + msg + "sig.verify() failed"); throw new SignatureException(msg + "Invalid PKCS #10 signature"); } } } catch (InvalidKeyException e) { logger.error("PKCS10: " + msg + e.getMessage()); throw new SignatureException(msg + "invalid key", e); } logger.debug("PKCS10: ends"); } public PKCS10(byte data[]) throws IOException, SignatureException, NoSuchAlgorithmException, java.security.NoSuchProviderException { this(data, true); } /** * Create the signed certificate request. This will later be * retrieved in either string or binary format. * * @param requester identifies the signer (by X.500 name) * and provides the private key used to sign. * @exception IOException on errors. * @exception CertificateException on certificate handling errors. * @exception SignatureException on signature handling errors. */ public void encodeAndSign(X500Signer requester) throws CertificateException, IOException, SignatureException { DerOutputStream out, scratch; byte certificateRequestInfo[]; byte sig[]; if (certificateRequest != null) throw new SignatureException("request is already signed"); subject = requester.getSigner(); /* * Encode cert request info, wrap in a sequence for signing */ scratch = new DerOutputStream(); scratch.putInteger(new BigInt(0)); // version zero subject.encode(scratch); // X.500 name subjectPublicKeyInfo.encode(scratch); // public key attributeSet.encode(scratch); out = new DerOutputStream(); out.write(DerValue.tag_Sequence, scratch); // wrap it! certificateRequestInfo = out.toByteArray(); scratch = out; /* * Sign it ... */ requester.update(certificateRequestInfo, 0, certificateRequestInfo.length); sig = requester.sign(); /* * Build guts of SIGNED macro */ requester.getAlgorithmId().encode(scratch); // sig algorithm scratch.putBitString(sig); // sig /* * Wrap those guts in a sequence */ out = new DerOutputStream(); out.write(DerValue.tag_Sequence, scratch); certificateRequest = out.toByteArray(); } /** * Returns the subject's name. */ public X500Name getSubjectName() { return subject; } /** * Returns the subject's public key. */ public X509Key getSubjectPublicKeyInfo() { return subjectPublicKeyInfo; } /** * Returns the additional attributes requested. */ public PKCS10Attributes getAttributes() { return attributeSet; } /** * Returns the encoded and signed certificate request as a * DER-encoded byte array. * * @return the certificate request, or null if encodeAndSign() * has not yet been called. */ public byte[] toByteArray() { return certificateRequest; } /** * Prints an E-Mailable version of the certificate request on the print * stream passed. The format is a common base64 encoded one, supported * by most Certificate Authorities because Netscape web servers have * used this for some time. Some certificate authorities expect some * more information, in particular contact information for the web * server administrator. * * @param out the print stream where the certificate request * will be printed. * @exception IOException when an output operation failed * @exception SignatureException when the certificate request was * not yet signed. */ public void print(PrintStream out) throws IOException, SignatureException { if (certificateRequest == null) throw new SignatureException("Cert request was not signed"); out.println(Cert.REQUEST_HEADER); out.print(Utils.base64encode(certificateRequest, true)); out.println(Cert.REQUEST_FOOTER); } /** * Provides a short description of this request. */ @Override public String toString() { return "[PKCS #10 certificate request:\n" + subjectPublicKeyInfo.toString() + " subject: <" + subject + ">" + "\n" + " attributes: " + attributeSet.toString() + "\n]"; } /** * Retrieve the PKCS10 CertificateRequestInfo as a byte array */ public byte[] getCertRequestInfo() { return certRequestInfo; } private X500Name subject; private X509Key subjectPublicKeyInfo; private PKCS10Attributes attributeSet; private byte certificateRequest[]; // signed private byte certRequestInfo[]; // inner content signed } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS10Attribute.java000066400000000000000000000205511412550063600300520ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.pkcs; import java.io.IOException; import java.io.OutputStream; import java.io.Serializable; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.security.cert.CertificateException; import org.mozilla.jss.netscape.security.util.DerEncoder; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; import org.mozilla.jss.netscape.security.x509.ACertAttrSet; import org.mozilla.jss.netscape.security.x509.CertAttrSet; import org.mozilla.jss.netscape.security.x509.Extensions; import org.mozilla.jss.netscape.security.x509.OIDMap; /** * Represent a PKCS Attribute. * *

* Attributes are addiitonal attributes which can be inserted in a PKCS certificate request. For example a * "Driving License Certificate" could have the driving license number as a attribute. * *

* Attributes are represented as a sequence of the attribute identifier (Object Identifier) and a set of DER encoded * attribute values. The current implementation only supports one value per attribute. * * ASN.1 definition of Attribute: * *

 * Attribute :: SEQUENCE {
 *    type    AttributeValue,
 *    values  SET OF AttributeValue
 * }
 * AttributeValue ::= ANY
 * 
* * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.13 */ public class PKCS10Attribute implements DerEncoder, Serializable { private static final long serialVersionUID = 2002480042340316170L; protected ObjectIdentifier attributeId = null; protected CertAttrSet attributeValue = null; /** * Default constructor. Used only by sub-classes. */ public PKCS10Attribute() { } /** * Constructs an attribute from a DER encoded array of bytes. */ public PKCS10Attribute(DerValue derVal) throws IOException { if (derVal.tag != DerValue.tag_Sequence) { throw new IOException("Sequence tag missing for PKCS10Attribute."); } DerInputStream in = derVal.toDerInputStream(); // Object identifier attributeId = in.getOID(); // System.out.println("attribute ID in pkcs10 "+attributeId.toString()); // Rest of the stuff is attribute value(s), wrapped in a SET. // For now, assume there is only one attribute value present. DerValue[] inAttrValues = in.getSet(1); int attrValueNum = inAttrValues.length; if (attrValueNum > 1) { throw new IOException("More than one value per attribute not supported"); } // Read the first attribute value DerValue inAttrValue = inAttrValues[0]; if (attributeId.equals(PKCS9Attribute.EXTENSION_REQUEST_OID)) { //pkcs9 extensionAttr try { // remove the tag //DerValue dv = inAttrValue.data.getDerValue(); // hack. toDerInputStream only gives one extension. DerInputStream fi = new DerInputStream(inAttrValue.toByteArray()); attributeValue = new Extensions(fi); //CertificateExtensions(fi); return; } catch (Exception e) { throw new IOException(e.toString()); } } byte[] val = inAttrValue.toByteArray(); Class[] params = { Object.class }; try { @SuppressWarnings("unchecked") Class extClass = (Class) OIDMap.getClass(attributeId); if (extClass != null) { Constructor cons = extClass.getConstructor(params); Object value = Array.newInstance(byte.class, val.length); for (int i = 0; i < val.length; i++) { Array.setByte(value, i, val[i]); } Object[] passed = new Object[] { value }; attributeValue = cons.newInstance(passed); } else { // attribute classes are usable for PKCS10 attributes. // this is used where the attributes are not actual // implemented extensions. attributeValue = new ACertAttrSet(inAttrValue); } } catch (InvocationTargetException invk) { throw new IOException(invk.getTargetException().getMessage(), invk); } catch (Exception e) { throw new IOException(e); } } /** * Constructs an attribute from individual components of ObjectIdentifier * and the DER encoded value. * * @param attributeId the ObjectIdentifier of the attribute. * @param attributeValue the CertAttrSet. */ public PKCS10Attribute(ObjectIdentifier attributeId, CertAttrSet attributeValue) { this.attributeId = attributeId; this.attributeValue = attributeValue; } /** * Constructs an attribute from another attribute. To be used for * creating decoded subclasses. * * @param attr the attribute to create from. */ public PKCS10Attribute(PKCS10Attribute attr) { this.attributeId = attr.attributeId; this.attributeValue = attr.attributeValue; } /** * Write the output to the DerOutputStream. * * @param out the OutputStream to write the attribute to. * @exception CertificateException on certificate encoding errors. * @exception IOException on encoding errors. */ public void encode(OutputStream out) throws CertificateException, IOException { try (DerOutputStream tmp = new DerOutputStream()) { // Encode the attribute value DerOutputStream outAttrValue = new DerOutputStream(); attributeValue.encode(outAttrValue); // Wrap the encoded attribute value into a SET DerValue outAttrValueSet = new DerValue(DerValue.tag_Set, outAttrValue.toByteArray()); // Create the attribute DerOutputStream outAttr = new DerOutputStream(); outAttr.putOID(attributeId); outAttr.putDerValue(outAttrValueSet); // Wrap the OID and the set of attribute values into a SEQUENCE tmp.write(DerValue.tag_Sequence, outAttr); // write the results to out out.write(tmp.toByteArray()); } } /** * DER encode this object onto an output stream. * Implements the DerEncoder interface. * * @param out * the OutputStream on which to write the DER encoding. * * @exception IOException on encoding errors. */ @Override public void derEncode(OutputStream out) throws IOException { try { encode(out); } catch (CertificateException ce) { IOException ioe = new IOException(ce.toString()); ioe.fillInStackTrace(); throw ioe; } } /** * Returns the ObjectIdentifier of the attribute. */ public ObjectIdentifier getAttributeId() { return (attributeId); } /** * Returns the attribute value as an byte array for further processing. */ public CertAttrSet getAttributeValue() { return (attributeValue); } /** * Returns the attribute in user readable form. */ @Override public String toString() { String s = "AttributeId: " + attributeId.toString() + "\n"; s += "AttributeValue: " + attributeValue.toString(); return (s); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS10Attributes.java000066400000000000000000000127201412550063600302340ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.pkcs; import java.io.IOException; import java.io.OutputStream; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerEncoder; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This class defines the PKCS10 attributes for the request. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.10 */ public class PKCS10Attributes extends Vector implements DerEncoder { public final static Logger logger = LoggerFactory.getLogger(PKCS10Attributes.class); /** * */ private static final long serialVersionUID = 1362260612357629542L; private Hashtable map; /** * Default constructor for the certificate attribute. */ public PKCS10Attributes() { map = new Hashtable(); } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the attributes from. * @exception IOException on decoding errors. */ public PKCS10Attributes(DerInputStream in) throws IOException { map = new Hashtable(); DerValue[] attrs = in.getSet(5, true); if (attrs != null) { for (int i = 0; i < attrs.length; i++) { PKCS10Attribute attr = new PKCS10Attribute(attrs[i]); addElement(attr); logger.debug("PKCS10Attributes: adding attribute: " + attr.getAttributeValue().getName()); map.put(attr.getAttributeValue().getName(), attr); } } } /** * Encode the attributes in DER form to the stream. * * @param out the OutputStream to marshal the contents to. * * @exception IOException on encoding errors. */ public void encode(OutputStream out) throws IOException { derEncode(out); } /** * Encode the attributes in DER form to the stream. * Implements the DerEncoder interface. * * @param out the OutputStream to marshal the contents to. * @exception IOException on encoding errors. */ @Override public void derEncode(OutputStream out) throws IOException { try (DerOutputStream attrOut = new DerOutputStream()) { // first copy the elements into an array PKCS10Attribute[] attribs = new PKCS10Attribute[size()]; copyInto(attribs); attrOut.putOrderedSetOf(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0), attribs); out.write(attrOut.toByteArray()); } catch (IOException e) { throw e; } } /** * Set the attribute value. */ public void setAttribute(String name, PKCS10Attribute attr) throws IOException { map.put(name, attr); addElement(attr); } /** * Get the attribute value. */ public PKCS10Attribute getAttribute(String name) throws IOException { PKCS10Attribute attr = map.get(name); /* if (attr == null) { throw new IOException("No attribute found with name " + name); } */ return (attr); } /** * Delete the attribute value. */ public void deleteAttribute(String name) throws IOException { PKCS10Attribute attr = map.get(name); if (attr == null) { throw new IOException("No attribute found with name " + name); } map.remove(name); removeElement(attr); } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getElements() { return map.elements(); } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((map == null) ? 0 : map.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; PKCS10Attributes other = (PKCS10Attributes) obj; if (map == null) { if (other.map != null) return false; } else if (!map.equals(other.map)) return false; return true; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS12.java000066400000000000000000000157301412550063600261730ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2016 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.pkcs; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; public class PKCS12 { // PKI OID: 2.16.840.1.113730.5 public final static OBJECT_IDENTIFIER PKI_OID = new OBJECT_IDENTIFIER("2.16.840.1.113730.5"); // PKCS #12 OID: 2.16.840.1.113730.5.1 public final static OBJECT_IDENTIFIER PKCS12_OID = PKI_OID.subBranch(1); // PKCS #12 attributes OID: 2.16.840.1.113730.5.1.1 public final static OBJECT_IDENTIFIER PKCS12_ATTRIBUTES_OID = PKCS12_OID.subBranch(1); // Certificate trust flags OID: 2.16.840.1.113730.5.1.1.1 public final static OBJECT_IDENTIFIER CERT_TRUST_FLAGS_OID = PKCS12_ATTRIBUTES_OID.subBranch(1); // based on certdb.h in NSS public final static int TERMINAL_RECORD = 1 << 0; public final static int TRUSTED = 1 << 1; public final static int SEND_WARN = 1 << 2; public final static int VALID_CA = 1 << 3; public final static int TRUSTED_CA = 1 << 4; public final static int NS_TRUSTED_CA = 1 << 5; public final static int USER = 1 << 6; public final static int TRUSTED_CLIENT_CA = 1 << 7; public final static int INVISIBLE_CA = 1 << 8; public final static int GOVT_APPROVED_CA = 1 << 9; public static boolean isFlagEnabled(int flag, int flags) { return (flag & flags) > 0; } // based on printflags() in secutil.c in NSS public static String encodeFlags(int flags) { StringBuffer sb = new StringBuffer(); if (isFlagEnabled(VALID_CA, flags) && !isFlagEnabled(TRUSTED_CA, flags) && !isFlagEnabled(TRUSTED_CLIENT_CA, flags)) sb.append("c"); if (isFlagEnabled(TERMINAL_RECORD, flags) && !isFlagEnabled(TRUSTED, flags)) sb.append("p"); if (isFlagEnabled(TRUSTED_CA, flags)) sb.append("C"); if (isFlagEnabled(TRUSTED_CLIENT_CA, flags)) sb.append("T"); if (isFlagEnabled(TRUSTED, flags)) sb.append("P"); if (isFlagEnabled(USER, flags)) sb.append("u"); if (isFlagEnabled(SEND_WARN, flags)) sb.append("w"); if (isFlagEnabled(INVISIBLE_CA, flags)) sb.append("I"); if (isFlagEnabled(GOVT_APPROVED_CA, flags)) sb.append("G"); return sb.toString(); } // based on CERT_DecodeTrustString() in certdb.c in NSS public static int decodeFlags(String flags) throws Exception { int value = 0; for (char c : flags.toCharArray()) { switch (c) { case 'p': value = value | TERMINAL_RECORD; break; case 'P': value = value | TRUSTED | TERMINAL_RECORD; break; case 'w': value = value | SEND_WARN; break; case 'c': value = value | VALID_CA; break; case 'T': value = value | TRUSTED_CLIENT_CA | VALID_CA; break; case 'C' : value = value | TRUSTED_CA | VALID_CA; break; case 'u': value = value | USER; break; case 'i': value = value | INVISIBLE_CA; break; case 'g': value = value | GOVT_APPROVED_CA; break; default: throw new Exception("Invalid trust flag: " + c); } } return value; } Map keyInfosByID = new LinkedHashMap(); Map certInfosByID = new LinkedHashMap(); Map certInfosByKeyID = new LinkedHashMap(); public PKCS12() { } public Collection getKeyInfos() { return keyInfosByID.values(); } public void addKeyInfo(PKCS12KeyInfo keyInfo) { keyInfosByID.put(new BigInteger(1, keyInfo.getID()), keyInfo); } public PKCS12KeyInfo getKeyInfoByID(byte[] id) { return keyInfosByID.get(new BigInteger(1, id)); } public PKCS12KeyInfo removeKeyInfoByID(byte[] id) { return keyInfosByID.remove(new BigInteger(1, id)); } public Collection getCertInfos() { return certInfosByID.values(); } public void addCertInfo(PKCS12CertInfo certInfo, boolean replace) { BigInteger id = new BigInteger(1, certInfo.getID()); if (!replace && certInfosByID.containsKey(id)) return; certInfosByID.put(id, certInfo); byte[] keyID = certInfo.getKeyID(); if (keyID == null) return; certInfosByKeyID.put(new BigInteger(1, keyID), certInfo); } public PKCS12CertInfo getCertInfoByID(byte[] id) { return certInfosByID.get(new BigInteger(1, id)); } public PKCS12CertInfo getCertInfoByKeyID(byte[] keyID) { return certInfosByKeyID.get(new BigInteger(1, keyID)); } public Collection getCertInfosByFriendlyName(String friendlyName) { Collection result = new ArrayList(); for (PKCS12CertInfo certInfo : certInfosByID.values()) { if (!friendlyName.equals(certInfo.getFriendlyName())) continue; result.add(certInfo); } return result; } public void removeCertInfoByFriendlyName(String friendlyName) throws Exception { Collection result = getCertInfosByFriendlyName(friendlyName); if (result.isEmpty()) { throw new Exception("Certificate not found: " + friendlyName); } for (PKCS12CertInfo certInfo : result) { BigInteger id = new BigInteger(1, certInfo.getID()); certInfosByID.remove(id); byte[] keyID = certInfo.getKeyID(); if (keyID == null) continue; certInfosByKeyID.remove(new BigInteger(1, keyID)); keyInfosByID.remove(new BigInteger(1, keyID)); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS12CertInfo.java000066400000000000000000000034711412550063600276240ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2016 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.pkcs; import org.mozilla.jss.netscape.security.x509.X509CertImpl; public class PKCS12CertInfo { private byte[] id; private X509CertImpl cert; private String friendlyName; private String trustFlags; private byte[] keyID; public PKCS12CertInfo() { } public byte[] getID() { return id; } public void setID(byte[] id) { this.id = id; } public X509CertImpl getCert() { return cert; } public void setCert(X509CertImpl cert) { this.cert = cert; } public String getFriendlyName() { return friendlyName; } public void setFriendlyName(String friendlyName) { this.friendlyName = friendlyName; } public String getTrustFlags() { return trustFlags; } public void setTrustFlags(String trustFlags) { this.trustFlags = trustFlags; } public byte[] getKeyID() { return keyID; } public void setKeyID(byte[] keyID) { this.keyID = keyID; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS12KeyInfo.java000066400000000000000000000045231412550063600274560ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2016 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.pkcs; import org.mozilla.jss.crypto.PrivateKey; /** * This object is used for carrying key info around. * * It does not handle raw key material (but it used to). * * FIXME: A clear refactoring opportunity exists. The 'privateKey' * field (and associated constructor) is only used during export, * and the 'epkiBytes' field (and associated constructor) is only * used during import. Therefore this should be two different * types. */ public class PKCS12KeyInfo { private PrivateKey privateKey; private byte[] epkiBytes; private byte[] id; private String friendlyName; public PKCS12KeyInfo() { } /** * Construct with a PrivateKey. This constructor is used * for moving the PrivateKey handle around during export. */ public PKCS12KeyInfo(PrivateKey k) { this.privateKey = k; } /** Construct with a (serialised) EncrypedPrivateKeyInfo. This * constructor is used for moving the EPKI data around during * import. */ public PKCS12KeyInfo(byte[] epkiBytes) { this.epkiBytes = epkiBytes; } public PrivateKey getPrivateKey() { return this.privateKey; } public byte[] getEncryptedPrivateKeyInfoBytes() { return epkiBytes; } public byte[] getID() { return id; } public void setID(byte[] id) { this.id = id; } public String getFriendlyName() { return friendlyName; } public void setFriendlyName(String friendlyName) { this.friendlyName = friendlyName; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS12Util.java000066400000000000000000001026631412550063600270330ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2016 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.pkcs; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.math.BigInteger; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.security.MessageDigest; import java.security.Principal; import java.security.PublicKey; import java.security.SecureRandom; import java.security.cert.CertificateException; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.ArrayList; import org.apache.commons.lang3.StringUtils; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BMPString; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.SET; import org.mozilla.jss.crypto.CryptoStore; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.EncryptionAlgorithm; import org.mozilla.jss.crypto.InternalCertificate; import org.mozilla.jss.crypto.NoSuchItemOnTokenException; import org.mozilla.jss.crypto.ObjectNotFoundException; import org.mozilla.jss.crypto.PBEAlgorithm; import org.mozilla.jss.crypto.PrivateKey; import org.mozilla.jss.crypto.X509Certificate; import org.mozilla.jss.pkcs11.PK11Store; import org.mozilla.jss.pkcs12.AuthenticatedSafes; import org.mozilla.jss.pkcs12.CertBag; import org.mozilla.jss.pkcs12.PFX; import org.mozilla.jss.pkcs12.PasswordConverter; import org.mozilla.jss.pkcs12.SafeBag; import org.mozilla.jss.pkix.primitive.Attribute; import org.mozilla.jss.pkix.primitive.EncryptedPrivateKeyInfo; import org.mozilla.jss.util.Password; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.naming.ldap.LdapName; import javax.naming.ldap.Rdn; import javax.naming.InvalidNameException; import org.mozilla.jss.netscape.security.util.Utils; import org.mozilla.jss.netscape.security.x509.X509CertImpl; public class PKCS12Util { private static Logger logger = LoggerFactory.getLogger(PKCS12Util.class); public final static String NO_ENCRYPTION = "none"; public final static List SUPPORTED_CERT_ENCRYPTIONS = Arrays.asList(new PBEAlgorithm[] { null, // none PBEAlgorithm.PBE_SHA1_RC2_40_CBC }); public final static List SUPPORTED_KEY_ENCRYPTIONS = Arrays.asList(new PBEAlgorithm[] { PBEAlgorithm.PBE_PKCS5_PBES2, PBEAlgorithm.PBE_SHA1_DES3_CBC }); public final static PBEAlgorithm DEFAULT_CERT_ENCRYPTION = SUPPORTED_CERT_ENCRYPTIONS.get(0); public final static String DEFAULT_CERT_ENCRYPTION_NAME = NO_ENCRYPTION; public final static PBEAlgorithm DEFAULT_KEY_ENCRYPTION = SUPPORTED_KEY_ENCRYPTIONS.get(0); public final static String DEFAULT_KEY_ENCRYPTION_NAME = DEFAULT_KEY_ENCRYPTION.toString(); SecureRandom random; PBEAlgorithm certEncryption = DEFAULT_CERT_ENCRYPTION; PBEAlgorithm keyEncryption = DEFAULT_KEY_ENCRYPTION; boolean trustFlagsEnabled = true; public PKCS12Util() throws Exception { random = SecureRandom.getInstance("pkcs11prng", "Mozilla-JSS"); } public void setCertEncryption(String name) throws Exception { for (PBEAlgorithm algorithm : SUPPORTED_CERT_ENCRYPTIONS) { if (algorithm == null) { if (NO_ENCRYPTION.equals(name)) { this.certEncryption = null; return; } } else if (algorithm.toString().equals(name)) { this.certEncryption = algorithm; return; } } throw new Exception("Unsupported certificate encryption: " + name); } public void setCertEncryption(PBEAlgorithm algorithm) throws Exception { this.certEncryption = algorithm; } public PBEAlgorithm getCertEncryption() { return certEncryption; } public void setKeyEncryption(String name) throws Exception { for (PBEAlgorithm algorithm : SUPPORTED_KEY_ENCRYPTIONS) { if (algorithm == null) { if (NO_ENCRYPTION.equals(name)) { this.keyEncryption = null; return; } } else if (algorithm.toString().equals(name)) { this.keyEncryption = algorithm; return; } } throw new Exception("Unsupported key encryption: " + name); } public void setKeyEncryption(PBEAlgorithm algorithm) throws Exception { this.keyEncryption = algorithm; } public PBEAlgorithm getKeyEncryption() { return keyEncryption; } public boolean isTrustFlagsEnabled() { return trustFlagsEnabled; } public void setTrustFlagsEnabled(boolean trustFlagsEnabled) { this.trustFlagsEnabled = trustFlagsEnabled; } public String getTrustFlags(X509Certificate cert) { InternalCertificate icert = (InternalCertificate) cert; StringBuilder sb = new StringBuilder(); sb.append(PKCS12.encodeFlags(icert.getSSLTrust())); sb.append(","); sb.append(PKCS12.encodeFlags(icert.getEmailTrust())); sb.append(","); sb.append(PKCS12.encodeFlags(icert.getObjectSigningTrust())); return sb.toString(); } public void setTrustFlags(X509Certificate cert, String trustFlags) throws Exception { InternalCertificate icert = (InternalCertificate) cert; String[] flags = trustFlags.split(",", -1); // don't remove empty string if (flags.length < 3) throw new Exception("Invalid trust flags: " + trustFlags); icert.setSSLTrust(PKCS12.decodeFlags(flags[0])); icert.setEmailTrust(PKCS12.decodeFlags(flags[1])); icert.setObjectSigningTrust(PKCS12.decodeFlags(flags[2])); } /** * Add a private key to the PKCS #12 object. * * The PKCS12KeyInfo object received comes about in two * different scenarios: * * - The private key could be in encrypted byte[] form (e.g. * when we have merely loaded a PKCS #12 file for inspection * or e.g. to delete a certificate and its associated key). * In this case we simply re-use this encrypted private key * info byte[]. * * - The private key could be a be an NSS PrivateKey handle. In * this case we must export the PrivateKey from the token to * obtain the EncryptedPrivateKeyInfo. * * The common final step is to add the encrypted private key * data to a "Shrouded Key Bag" to the PKCS #12 object. * Unencrypted key material is never seen. */ public void addKeyBag(PKCS12KeyInfo keyInfo, Password password, SEQUENCE encSafeContents) throws Exception { byte[] keyID = keyInfo.getID(); logger.debug(" - Key ID: " + Utils.HexEncode(keyID)); ASN1Value content; byte[] epkiBytes = keyInfo.getEncryptedPrivateKeyInfoBytes(); if (epkiBytes != null) { // private key already encrypted content = new ANY(epkiBytes); } else { PrivateKey privateKey = keyInfo.getPrivateKey(); if (privateKey == null) { throw new Exception("Missing private key for " + keyInfo.getFriendlyName()); } CryptoToken token = CryptoManager.getInstance().getInternalKeyStorageToken(); if (keyEncryption == PBEAlgorithm.PBE_SHA1_DES3_CBC) { content = create_EPKI_with_PBE_SHA1_DES3_CBC(token, privateKey, password); } else if (keyEncryption == PBEAlgorithm.PBE_PKCS5_PBES2) { content = create_EPKI_with_PBE_PKCS5_PBES2(token, privateKey, password); } else { throw new Exception("Unsupported key encryption: " + keyEncryption); } } SET keyAttrs = createKeyBagAttrs(keyInfo); SafeBag safeBag = new SafeBag(SafeBag.PKCS8_SHROUDED_KEY_BAG, content, keyAttrs); encSafeContents.addElement(safeBag); } public ASN1Value create_EPKI_with_PBE_SHA1_DES3_CBC(CryptoToken token, PrivateKey privateKey, Password password) throws Exception { // Use the same salt size and number of iterations as in pk12util. byte[] salt = new byte[16]; random.nextBytes(salt); return EncryptedPrivateKeyInfo.createPBE( PBEAlgorithm.PBE_SHA1_DES3_CBC, password, salt, 100000, // iterations new PasswordConverter(), privateKey, token); } public ASN1Value create_EPKI_with_PBE_PKCS5_PBES2(CryptoToken token, PrivateKey privateKey, Password password) throws Exception { CryptoStore store = token.getCryptoStore(); byte[] bytes = store.getEncryptedPrivateKeyInfo( // For compatibility with OpenSSL and NSS >= 3.31, // do not BMPString-encode the passphrase when using // non-PKCS #12 PBE scheme such as PKCS #5 PBES2. // // The resulting PKCS #12 is not compatible with // NSS < 3.31. null, // password converter password, // NSS has a bug that causes any AES CBC encryption // to use AES-256, but AlgorithmID contains chosen // alg. To avoid mismatch, use AES_256_CBC. EncryptionAlgorithm.AES_256_CBC, 0, // iterations (default) privateKey); return new ANY(bytes); } public void addCertBag(PKCS12CertInfo certInfo, SEQUENCE safeContents) throws Exception { byte[] id = certInfo.getID(); logger.debug(" - Certificate ID: " + Utils.HexEncode(id)); X509CertImpl cert = certInfo.getCert(); ASN1Value certAsn1 = new OCTET_STRING(cert.getEncoded()); CertBag certBag = new CertBag(CertBag.X509_CERT_TYPE, certAsn1); SET certAttrs = createCertBagAttrs(certInfo); SafeBag safeBag = new SafeBag(SafeBag.CERT_BAG, certBag, certAttrs); safeContents.addElement(safeBag); } BigInteger createLocalID(X509Certificate cert) throws Exception { // SHA1 hash of the X509Cert DER encoding return createLocalID(cert.getEncoded()); } BigInteger createLocalID(byte[] bytes) throws Exception { MessageDigest md = MessageDigest.getInstance("SHA"); md.update(bytes); return new BigInteger(1, md.digest()); } SET createKeyBagAttrs(PKCS12KeyInfo keyInfo) throws Exception { SET attrs = new SET(); String friendlyName = keyInfo.getFriendlyName(); logger.debug(" Friendly name: " + friendlyName); SEQUENCE subjectAttr = new SEQUENCE(); subjectAttr.addElement(SafeBag.FRIENDLY_NAME); SET subjectSet = new SET(); subjectSet.addElement(new BMPString(friendlyName)); subjectAttr.addElement(subjectSet); attrs.addElement(subjectAttr); byte[] keyID = keyInfo.getID(); SEQUENCE localKeyAttr = new SEQUENCE(); localKeyAttr.addElement(SafeBag.LOCAL_KEY_ID); SET localKeySet = new SET(); localKeySet.addElement(new OCTET_STRING(keyID)); localKeyAttr.addElement(localKeySet); attrs.addElement(localKeyAttr); return attrs; } SET createCertBagAttrs(PKCS12CertInfo certInfo) throws Exception { SET attrs = new SET(); String friendlyName = certInfo.getFriendlyName(); logger.debug(" Friendly name: " + friendlyName); SEQUENCE nicknameAttr = new SEQUENCE(); nicknameAttr.addElement(SafeBag.FRIENDLY_NAME); SET nicknameSet = new SET(); nicknameSet.addElement(new BMPString(friendlyName)); nicknameAttr.addElement(nicknameSet); attrs.addElement(nicknameAttr); String trustFlags = certInfo.getTrustFlags(); if (trustFlags != null && trustFlagsEnabled) { logger.debug(" Trust flags: " + trustFlags); SEQUENCE trustFlagsAttr = new SEQUENCE(); trustFlagsAttr.addElement(PKCS12.CERT_TRUST_FLAGS_OID); SET trustFlagsSet = new SET(); trustFlagsSet.addElement(new BMPString(trustFlags)); trustFlagsAttr.addElement(trustFlagsSet); attrs.addElement(trustFlagsAttr); } byte[] keyID = certInfo.getKeyID(); if (keyID != null) { logger.debug(" Key ID: " + Utils.HexEncode(keyID)); SEQUENCE localKeyAttr = new SEQUENCE(); localKeyAttr.addElement(SafeBag.LOCAL_KEY_ID); SET localKeySet = new SET(); localKeySet.addElement(new OCTET_STRING(keyID)); localKeyAttr.addElement(localKeySet); attrs.addElement(localKeyAttr); } return attrs; } public void loadFromNSS(PKCS12 pkcs12) throws Exception { loadFromNSS(pkcs12, true, true); } public void loadFromNSS(PKCS12 pkcs12, boolean includeKey, boolean includeChain) throws Exception { logger.info("Loading certificates and keys from NSS database"); CryptoManager cm = CryptoManager.getInstance(); CryptoToken token = cm.getInternalKeyStorageToken(); CryptoStore store = token.getCryptoStore(); for (X509Certificate cert : store.getCertificates()) { loadCertFromNSS(pkcs12, cert, includeKey, includeChain); } } public void loadCertFromNSS( PKCS12 pkcs12, String nickname, boolean includeKey, boolean includeChain) throws Exception { loadCertFromNSS(pkcs12, nickname, includeKey, includeChain, null); } public void loadCertFromNSS( PKCS12 pkcs12, String nickname, boolean includeKey, boolean includeChain, String friendlyName) throws Exception { CryptoManager cm = CryptoManager.getInstance(); X509Certificate[] certs = cm.findCertsByNickname(nickname); if (certs == null || certs.length == 0) { throw new Exception("Certificate not found: " + nickname); } for (X509Certificate cert : certs) { loadCertFromNSS(pkcs12, cert, includeKey, includeChain, friendlyName); } } public void loadCertFromNSS( PKCS12 pkcs12, X509Certificate cert, boolean includeKey, boolean includeChain) throws Exception { loadCertFromNSS(pkcs12, cert, includeKey, includeChain, null); } public void loadCertFromNSS( PKCS12 pkcs12, X509Certificate cert, boolean includeKey, boolean includeChain, String friendlyName) throws Exception { CryptoManager cm = CryptoManager.getInstance(); PKCS12CertInfo certInfo = createCertInfoFromNSS(cert, friendlyName); pkcs12.addCertInfo(certInfo, true); byte[] id = certInfo.getID(); logger.debug(" - Certificate ID: " + Utils.HexEncode(id)); logger.debug(" Friendly name: " + certInfo.getFriendlyName()); logger.debug(" Trust flags: " + certInfo.getTrustFlags()); if (includeKey) { // load key info if exists try { PrivateKey privateKey = cm.findPrivKeyByCert(cert); PKCS12KeyInfo keyInfo = createKeyInfoFromNSS(cert, privateKey, friendlyName); pkcs12.addKeyInfo(keyInfo); byte[] keyID = keyInfo.getID(); certInfo.setKeyID(keyID); logger.debug(" Key ID: " + Utils.HexEncode(keyID)); } catch (ObjectNotFoundException e) { logger.debug("Certificate has no private key"); } } if (includeChain) { // load cert chain X509Certificate[] certChain = cm.buildCertificateChain(cert); if (certChain.length > 1) { logger.debug(" Certificate Chain:"); } for (int i = 1; i < certChain.length; i++) { X509Certificate caCert = certChain[i]; PKCS12CertInfo caCertInfo = createCertInfoFromNSS(caCert); pkcs12.addCertInfo(caCertInfo, false); byte[] caCertID = caCertInfo.getID(); logger.debug(" - Certificate ID: " + Utils.HexEncode(caCertID)); logger.debug(" Friendly name: " + caCertInfo.getFriendlyName()); logger.debug(" Trust flags: " + caCertInfo.getTrustFlags()); } } } public PKCS12CertInfo createCertInfoFromNSS( X509Certificate cert) throws Exception { return createCertInfoFromNSS(cert, null); } public PKCS12CertInfo createCertInfoFromNSS( X509Certificate cert, String friendlyName) throws Exception { // generate cert ID from SHA-1 hash of cert data byte[] id = SafeBag.getLocalKeyIDFromCert(cert.getEncoded()); if (friendlyName == null) { friendlyName = cert.getNickname(); } X509CertImpl certImpl = new X509CertImpl(cert.getEncoded()); String trustFlags = getTrustFlags(cert); PKCS12CertInfo certInfo = new PKCS12CertInfo(); certInfo.setID(id); certInfo.setFriendlyName(friendlyName); certInfo.setCert(certImpl); certInfo.setTrustFlags(trustFlags); return certInfo; } public PKCS12KeyInfo createKeyInfoFromNSS( X509Certificate cert, PrivateKey privateKey) throws Exception { return createKeyInfoFromNSS(cert, privateKey, null); } public PKCS12KeyInfo createKeyInfoFromNSS( X509Certificate cert, PrivateKey privateKey, String friendlyName) throws Exception { byte[] keyID = privateKey.getUniqueID(); if (friendlyName == null) { friendlyName = cert.getNickname(); } PKCS12KeyInfo keyInfo = new PKCS12KeyInfo(privateKey); keyInfo.setID(keyID); keyInfo.setFriendlyName(friendlyName); return keyInfo; } public PFX generatePFX(PKCS12 pkcs12, Password password) throws Exception { logger.info("Generating PKCS #12 data"); AuthenticatedSafes authSafes = new AuthenticatedSafes(); Collection keyInfos = pkcs12.getKeyInfos(); Collection certInfos = pkcs12.getCertInfos(); if (!keyInfos.isEmpty()) { SEQUENCE keySafeContents = new SEQUENCE(); for (PKCS12KeyInfo keyInfo : keyInfos) { addKeyBag(keyInfo, password, keySafeContents); } authSafes.addSafeContents(keySafeContents); } if (!certInfos.isEmpty()) { SEQUENCE certSafeContents = new SEQUENCE(); for (PKCS12CertInfo certInfo : certInfos) { addCertBag(certInfo, certSafeContents); } if (certEncryption == null) { authSafes.addSafeContents(certSafeContents); } else if (certEncryption == PBEAlgorithm.PBE_SHA1_RC2_40_CBC) { byte[] salt = new byte[16]; random.nextBytes(salt); authSafes.addEncryptedSafeContents( certEncryption, password, salt, 100000, // iterations certSafeContents); } else { throw new Exception("Unsupported certificate encryption: " + certEncryption); } } PFX pfx = new PFX(authSafes); // Use the same salt size and number of iterations as in pk12util. byte[] salt = new byte[16]; random.nextBytes(salt); pfx.computeMacData(password, salt, 100000); return pfx; } public void storeIntoFile(PKCS12 pkcs12, String filename, Password password) throws Exception { PFX pfx = generatePFX(pkcs12, password); logger.info("Storing PKCS #12 data into " + filename); ByteArrayOutputStream bos = new ByteArrayOutputStream(); pfx.encode(bos); byte[] data = bos.toByteArray(); try (FileOutputStream fos = new FileOutputStream(filename)) { fos.write(data); } } /** * Loads key bags (for IMPORT and other operations on existing * PKCS #12 files). Does not decrypt EncryptedPrivateKeyInfo * values, but stores them in PKCS12KeyInfo objects for possible * later use. */ public PKCS12KeyInfo getKeyInfo(SafeBag bag, Password password) throws Exception { PKCS12KeyInfo keyInfo = new PKCS12KeyInfo(bag.getBagContent().getEncoded()); // get key attributes SET bagAttrs = bag.getBagAttributes(); for (int i = 0; bagAttrs != null && i < bagAttrs.size(); i++) { Attribute attr = (Attribute) bagAttrs.elementAt(i); OBJECT_IDENTIFIER oid = attr.getType(); if (oid.equals(SafeBag.FRIENDLY_NAME)) { SET values = attr.getValues(); ANY value = (ANY) values.elementAt(0); ByteArrayInputStream bis = new ByteArrayInputStream(value.getEncoded()); BMPString friendlyName = (BMPString) new BMPString.Template().decode(bis); keyInfo.setFriendlyName(friendlyName.toString()); logger.debug(" Friendly name: " + keyInfo.getFriendlyName()); } else if (oid.equals(SafeBag.LOCAL_KEY_ID)) { SET values = attr.getValues(); ANY value = (ANY) values.elementAt(0); ByteArrayInputStream bis = new ByteArrayInputStream(value.getEncoded()); OCTET_STRING keyIdAsn1 = (OCTET_STRING) new OCTET_STRING.Template().decode(bis); byte[] keyID = keyIdAsn1.toByteArray(); keyInfo.setID(keyID); } else { logger.warn(" " + oid + ": " + attr.getValues()); } } return keyInfo; } public PKCS12CertInfo getCertInfo(SafeBag bag) throws Exception { PKCS12CertInfo certInfo = new PKCS12CertInfo(); CertBag certBag = (CertBag) bag.getInterpretedBagContent(); OCTET_STRING certStr = (OCTET_STRING) certBag.getInterpretedCert(); byte[] x509cert = certStr.toByteArray(); // generate cert ID from SHA-1 hash of cert data byte[] id = SafeBag.getLocalKeyIDFromCert(x509cert); certInfo.setID(id); logger.debug(" Certificate ID: " + Utils.HexEncode(id)); X509CertImpl cert = new X509CertImpl(x509cert); certInfo.setCert(cert); Principal subjectDN = cert.getSubjectDN(); logger.debug(" Subject DN: " + subjectDN); SET bagAttrs = bag.getBagAttributes(); for (int i = 0; bagAttrs != null && i < bagAttrs.size(); i++) { Attribute attr = (Attribute) bagAttrs.elementAt(i); OBJECT_IDENTIFIER oid = attr.getType(); if (oid.equals(SafeBag.FRIENDLY_NAME)) { SET values = attr.getValues(); ANY value = (ANY) values.elementAt(0); ByteArrayInputStream bis = new ByteArrayInputStream(value.getEncoded()); BMPString friendlyName = (BMPString) (new BMPString.Template()).decode(bis); certInfo.setFriendlyName(friendlyName.toString()); logger.debug(" Friendly name: " + certInfo.getFriendlyName()); } else if (oid.equals(SafeBag.LOCAL_KEY_ID)) { SET values = attr.getValues(); ANY value = (ANY) values.elementAt(0); ByteArrayInputStream bis = new ByteArrayInputStream(value.getEncoded()); OCTET_STRING keyIdAsn1 = (OCTET_STRING) new OCTET_STRING.Template().decode(bis); byte[] keyID = keyIdAsn1.toByteArray(); certInfo.setKeyID(keyID); logger.debug(" Key ID: " + Utils.HexEncode(keyID)); } else if (oid.equals(PKCS12.CERT_TRUST_FLAGS_OID) && trustFlagsEnabled) { SET values = attr.getValues(); ANY value = (ANY) values.elementAt(0); ByteArrayInputStream is = new ByteArrayInputStream(value.getEncoded()); BMPString trustFlagsAsn1 = (BMPString) (new BMPString.Template()).decode(is); String trustFlags = trustFlagsAsn1.toString(); certInfo.setTrustFlags(trustFlags); logger.debug(" Trust flags: " + trustFlags); } else { logger.warn(" " + oid + ": " + attr.getValues()); } } if (certInfo.getFriendlyName() == null) { logger.debug(" Generating new friendly name"); LdapName dn = new LdapName(subjectDN.getName()); ArrayList values = new ArrayList(); // The getRdns method returns the list in reverse order // therefore, we must traverse in reverse order. List rdns = dn.getRdns(); for (int i = rdns.size() - 1; i >= 0; i--) { Rdn rdn = rdns.get(i); values.add(rdn.getValue().toString()); } String friendlyName = StringUtils.join(values, " - "); certInfo.setFriendlyName(friendlyName); logger.debug(" Friendly name: " + friendlyName); } return certInfo; } public void getKeyInfos(PKCS12 pkcs12, PFX pfx, Password password) throws Exception { logger.debug("Load encrypted private keys:"); AuthenticatedSafes safes = pfx.getAuthSafes(); for (int i = 0; i < safes.getSize(); i++) { SEQUENCE contents = safes.getSafeContentsAt(password, i); for (int j = 0; j < contents.size(); j++) { SafeBag bag = (SafeBag) contents.elementAt(j); OBJECT_IDENTIFIER oid = bag.getBagType(); if (!oid.equals(SafeBag.PKCS8_SHROUDED_KEY_BAG)) continue; logger.debug(" - Private key:"); PKCS12KeyInfo keyInfo = getKeyInfo(bag, password); pkcs12.addKeyInfo(keyInfo); } } } public void getCertInfos(PKCS12 pkcs12, PFX pfx, Password password) throws Exception { logger.debug("Loading certificates:"); AuthenticatedSafes safes = pfx.getAuthSafes(); for (int i = 0; i < safes.getSize(); i++) { SEQUENCE contents = safes.getSafeContentsAt(password, i); for (int j = 0; j < contents.size(); j++) { SafeBag bag = (SafeBag) contents.elementAt(j); OBJECT_IDENTIFIER oid = bag.getBagType(); if (!oid.equals(SafeBag.CERT_BAG)) continue; logger.debug(" - Certificate:"); PKCS12CertInfo certInfo = getCertInfo(bag); pkcs12.addCertInfo(certInfo, true); } } } public PKCS12 loadFromFile(String filename, Password password) throws Exception { logger.info("Loading PKCS #12 file"); Path path = Paths.get(filename); byte[] b = Files.readAllBytes(path); return loadFromByteArray(b, password); } public PKCS12 loadFromByteArray(byte[] b, Password password) throws Exception { ByteArrayInputStream bis = new ByteArrayInputStream(b); PFX pfx = (PFX) (new PFX.Template()).decode(bis); PKCS12 pkcs12 = new PKCS12(); StringBuffer reason = new StringBuffer(); boolean valid = pfx.verifyAuthSafes(password, reason); if (!valid) { throw new Exception("Unable to validate PKCS #12 file: " + reason); } getKeyInfos(pkcs12, pfx, password); getCertInfos(pkcs12, pfx, password); return pkcs12; } public PKCS12 loadFromFile(String filename) throws Exception { return loadFromFile(filename, null); } public PrivateKey.Type getPrivateKeyType(PublicKey publicKey) { if (publicKey.getAlgorithm().equals("EC")) { return PrivateKey.Type.EC; } return PrivateKey.Type.RSA; } public PKCS12CertInfo getCertBySubjectDN(PKCS12 pkcs12, String subjectDN) throws CertificateException { for (PKCS12CertInfo certInfo : pkcs12.getCertInfos()) { Principal certSubjectDN = certInfo.getCert().getSubjectDN(); try { LdapName certSubjdn = new LdapName(certSubjectDN.toString()); LdapName subjDn = new LdapName(subjectDN); if(certSubjdn.equals(subjDn)) return certInfo; } catch (InvalidNameException e) { return null; } } return null; } public void importKey( PKCS12 pkcs12, Password password, String nickname, PKCS12KeyInfo keyInfo) throws Exception { PKCS12CertInfo certInfo = pkcs12.getCertInfoByKeyID(keyInfo.getID()); if (certInfo == null) { logger.debug("Private key has no certificate, ignore"); return; } CryptoManager cm = CryptoManager.getInstance(); CryptoToken token = cm.getInternalKeyStorageToken(); PK11Store store = (PK11Store)token.getCryptoStore(); X509CertImpl certImpl = certInfo.getCert(); X509Certificate cert = cm.importCACertPackage(certImpl.getEncoded()); // get public key PublicKey publicKey = cert.getPublicKey(); byte[] epkiBytes = keyInfo.getEncryptedPrivateKeyInfoBytes(); if (epkiBytes == null) { logger.debug( "No EncryptedPrivateKeyInfo for key '" + keyInfo.getFriendlyName() + "'; skipping key"); } try { // first true without BMPString-encoding the passphrase. store.importEncryptedPrivateKeyInfo( null, password, nickname, publicKey, epkiBytes); } catch (Exception e) { // if that failed, try again with BMPString-encoded // passphrase. This is required for PKCS #12 PBE // schemes and for PKCS #12 files using PBES2 generated // by NSS < 3.31 store.importEncryptedPrivateKeyInfo( new PasswordConverter(), password, nickname, publicKey, epkiBytes); } // delete the cert again (it will be imported again later // with the correct nickname) try { store.deleteCertOnly(cert); } catch (NoSuchItemOnTokenException e) { // this is OK } } /** * Store a certificate (and key, if present) in NSSDB. */ public void storeCertIntoNSS( PKCS12 pkcs12, Password password, PKCS12CertInfo certInfo, boolean overwrite) throws Exception { CryptoManager cm = CryptoManager.getInstance(); CryptoToken ct = cm.getInternalKeyStorageToken(); CryptoStore store = ct.getCryptoStore(); String nickname = certInfo.getFriendlyName(); for (X509Certificate cert : cm.findCertsByNickname(nickname)) { if (!overwrite) { return; } store.deleteCert(cert); } X509CertImpl certImpl = certInfo.getCert(); X509Certificate cert; byte[] keyID = certInfo.getKeyID(); if (keyID != null) { // cert has key logger.debug("Importing private key for " + certInfo.getFriendlyName()); PKCS12KeyInfo keyInfo = pkcs12.getKeyInfoByID(keyID); importKey(pkcs12, password, certInfo.getFriendlyName(), keyInfo); logger.debug("Importing user certificate " + certInfo.getFriendlyName()); cert = cm.importUserCACertPackage( certImpl.getEncoded(), certInfo.getFriendlyName()); } else { // cert has no key logger.debug("Importing CA certificate " + certInfo.getFriendlyName()); // Note: JSS does not preserve CA certificate nickname cert = cm.importCACertPackage(certImpl.getEncoded()); } String trustFlags = certInfo.getTrustFlags(); if (trustFlags != null && trustFlagsEnabled) { setTrustFlags(cert, trustFlags); } } public void storeCertIntoNSS(PKCS12 pkcs12, Password password, String nickname, boolean overwrite) throws Exception { Collection certInfos = pkcs12.getCertInfosByFriendlyName(nickname); for (PKCS12CertInfo certInfo : certInfos) { storeCertIntoNSS(pkcs12, password, certInfo, overwrite); } } public void storeIntoNSS( PKCS12 pkcs12, Password password, boolean overwrite) throws Exception { logger.info("Storing data into NSS database"); for (PKCS12CertInfo certInfo : pkcs12.getCertInfos()) { storeCertIntoNSS(pkcs12, password, certInfo, overwrite); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS7.java000066400000000000000000000417001412550063600261130ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.pkcs; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.io.StringReader; import java.io.StringWriter; import java.math.BigInteger; import java.security.NoSuchAlgorithmException; import java.security.SignatureException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Vector; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; import org.mozilla.jss.netscape.security.util.Utils; import org.mozilla.jss.netscape.security.x509.AlgorithmId; import org.mozilla.jss.netscape.security.x509.X500Name; import org.mozilla.jss.netscape.security.x509.X509CertImpl; /** * PKCS7 as defined in RSA Laboratories PKCS7 Technical Note. Profile * Supports only SignedData ContentInfo * type, where to the type of data signed is plain Data. * For signedData, crls, attributes and * PKCS#6 Extended Certificates are not supported. * * @version 1.33 97/12/10 * @author Benjamin Renaud */ public class PKCS7 { public final static String HEADER = "-----BEGIN PKCS7-----"; public final static String FOOTER = "-----END PKCS7-----"; private ObjectIdentifier contentType; // the ASN.1 members for a signedData (and other) contentTypes private BigInt version; private AlgorithmId[] digestAlgorithmIds; private ContentInfo contentInfo; private X509Certificate[] certificates; private SignerInfo[] signerInfos; /** * Unmarshals a PKCS7 block from its encoded form, parsing the * encoded bytes from the InputStream. * * @param in an input stream holding at least one PKCS7 block. * @exception ParsingException on parsing errors. * @exception IOException on other errors. */ public PKCS7(InputStream in) throws ParsingException, IOException { DataInputStream dis = new DataInputStream(in); int len = 0; byte[] newbuf = new byte[len]; byte[] oldbuf = new byte[len]; byte[] data = new byte[len]; do { newbuf = new byte[dis.available()]; len += dis.available(); dis.readFully(newbuf); data = new byte[len]; System.arraycopy(oldbuf, 0, data, 0, oldbuf.length); System.arraycopy(newbuf, 0, data, oldbuf.length, newbuf.length); oldbuf = new byte[len]; System.arraycopy(data, 0, oldbuf, 0, data.length); } while (dis.available() > 0); parse(new DerInputStream(data)); } /** * Unmarshals a PKCS7 block from its encoded form, parsing the * encoded bytes from the DerInputStream. * * @param derin a DerInputStream holding at least one PKCS7 block. * @exception ParsingException on parsing errors. */ public PKCS7(DerInputStream derin) throws ParsingException { parse(derin); } /** * Unmarshals a PKCS7 block from its encoded form, parsing the * encoded bytes. * * @param bytes the encoded bytes. * @exception ParsingException on parsing errors. */ public PKCS7(byte[] bytes) throws ParsingException { DerInputStream derin = new DerInputStream(bytes); parse(derin); } /** * Unmarshals a PKCS7 block from PEM format. * * @param input the PKCS7 block in PEM format. * @exception ParsingException on parsing errors. */ public PKCS7(String input) throws ParsingException, IOException { StringBuilder sb = new StringBuilder(); try (StringReader sr = new StringReader(input.trim()); BufferedReader in = new BufferedReader(sr)) { String line; // skip everything up to header String header = null; while ((line = in.readLine()) != null) { if (HEADER.equals(line)) { header = line; break; } } if (header == null) { throw new ParsingException("Missing PKCS #7 header"); } // store everything up to footer String footer = null; while ((line = in.readLine()) != null) { if (FOOTER.equals(line)) { footer = line; break; } sb.append(line); } if (footer == null) { throw new ParsingException("Missing PKCS #7 footer"); } } byte[] bytes = Utils.base64decode(sb.toString()); parse(new DerInputStream(bytes)); } private void parse(DerInputStream derin) throws ParsingException { try { ContentInfo contentInfo = new ContentInfo(derin); contentType = contentInfo.contentType; if (contentType.equals(ContentInfo.SIGNED_DATA_OID)) { parseSignedData(contentInfo.getContent()); } else { throw new ParsingException("content type " + contentType + " not supported."); } } catch (IOException e) { ParsingException pe = new ParsingException("IOException: " + e.getMessage()); pe.fillInStackTrace(); throw pe; } } /** * Construct an initialized PKCS7 block. * * @param digestAlgorithmIds the message digest algorithm identifiers. * @param contentInfo the content information. * @param certificates an array of X.509 certificates. * @param signerInfos an array of signer information. */ public PKCS7(AlgorithmId[] digestAlgorithmIds, ContentInfo contentInfo, X509Certificate[] certificates, SignerInfo[] signerInfos) { version = new BigInt(1); this.digestAlgorithmIds = digestAlgorithmIds; this.contentInfo = contentInfo; this.certificates = certificates; this.signerInfos = signerInfos; } /** * Construct PKCS7 from an array of certificates. * * @param certs Array of certificates. */ public PKCS7(X509Certificate[] certs) { this(new AlgorithmId[0], new ContentInfo(new byte[0]), certs, new SignerInfo[0]); } private void parseSignedData(DerValue val) throws ParsingException, IOException { DerInputStream dis = val.toDerInputStream(); // Version version = dis.getInteger(); // digestAlgorithmIds DerValue[] digestAlgorithmIdVals = dis.getSet(1); int len = digestAlgorithmIdVals.length; digestAlgorithmIds = new AlgorithmId[len]; try { for (int i = 0; i < len; i++) { DerValue oid = digestAlgorithmIdVals[i]; digestAlgorithmIds[i] = AlgorithmId.parse(oid); } } catch (IOException e) { ParsingException pe = new ParsingException("Error parsing digest AlgorithmId IDs: " + e.getMessage()); pe.fillInStackTrace(); throw pe; } // contentInfo contentInfo = new ContentInfo(dis); /* * check if certificates (implicit tag) are provided * (certificates are OPTIONAL) */ if ((byte) (dis.peekByte()) == (byte) 0xA0) { DerValue[] certificateVals = dis.getSet(2, true); len = certificateVals.length; certificates = new X509Certificate[len]; for (int i = 0; i < len; i++) { try { X509Certificate cert = new X509CertImpl(certificateVals[i]); certificates[i] = cert; } catch (CertificateException e) { ParsingException pe = new ParsingException("CertificateException: " + e.getMessage()); pe.fillInStackTrace(); throw pe; } } } // check if crls (implicit tag) are provided (crls are OPTIONAL) if ((byte) (dis.peekByte()) == (byte) 0xA1) { dis.getSet(0, true); } // signerInfos DerValue[] signerInfoVals = dis.getSet(1); len = signerInfoVals.length; signerInfos = new SignerInfo[len]; for (int i = 0; i < len; i++) { DerInputStream in = signerInfoVals[i].toDerInputStream(); signerInfos[i] = new SignerInfo(in); } } /** * Encodes the signed data to an output stream. * * @param out the output stream to write the encoded data to. * @exception IOException on encoding errors. */ public void encodeSignedData(OutputStream out) throws IOException { DerOutputStream derout = new DerOutputStream(); encodeSignedData(derout, true); out.write(derout.toByteArray()); } /** * Like method above but not sorted. */ public void encodeSignedData(OutputStream out, boolean sort) throws IOException { DerOutputStream derout = new DerOutputStream(); encodeSignedData(derout, sort); out.write(derout.toByteArray()); } /** * encode signed data, sort certs by default. */ public void encodeSignedData(DerOutputStream out) throws IOException { encodeSignedData(out, true); } /** * Encodes the signed data to a DerOutputStream. * * @param out the DerOutputStream to write the encoded data to. * @exception IOException on encoding errors. */ public void encodeSignedData(DerOutputStream out, boolean sort) throws IOException { DerOutputStream signedData = new DerOutputStream(); // version signedData.putInteger(version); // digestAlgorithmIds signedData.putOrderedSetOf(DerValue.tag_Set, digestAlgorithmIds); // contentInfo contentInfo.encode(signedData); // cast to X509CertImpl[] since X509CertImpl implements DerEncoder X509CertImpl implCerts[] = new X509CertImpl[certificates.length]; try { for (int i = 0; i < certificates.length; i++) { implCerts[i] = (X509CertImpl) certificates[i]; } } catch (ClassCastException e) { throw new IOException( "Certificates in PKCS7 must be of class " + "org.mozilla.jss.netscape.security.X509CertImpl: " + e.getMessage(), e); } // Add the certificate set (tagged with [0] IMPLICIT) // to the signed data if (sort) { signedData.putOrderedSetOf((byte) 0xA0, implCerts); } else { signedData.putSet((byte) 0xA0, implCerts); } // no crls (OPTIONAL field) // signerInfos signedData.putOrderedSetOf(DerValue.tag_Set, signerInfos); // making it a signed data block DerValue signedDataSeq = new DerValue(DerValue.tag_Sequence, signedData.toByteArray()); // making it a content info sequence ContentInfo block = new ContentInfo(ContentInfo.SIGNED_DATA_OID, signedDataSeq); // writing out the contentInfo sequence block.encode(out); } /** * This verifies a given SignerInfo. * * @param info the signer information. * @param bytes the DER encoded content information. * * @exception NoSuchAlgorithmException on unrecognized algorithms. * @exception SignatureException on signature handling errors. */ public SignerInfo verify(SignerInfo info, byte[] bytes) throws NoSuchAlgorithmException, SignatureException { return info.verify(this, bytes); } /** * Returns all signerInfos which self-verify. * * @param bytes the DER encoded content information. * * @exception NoSuchAlgorithmException on unrecognized algorithms. * @exception SignatureException on signature handling errors. */ public SignerInfo[] verify(byte[] bytes) throws NoSuchAlgorithmException, SignatureException { Vector intResult = new Vector(); for (int i = 0; i < signerInfos.length; i++) { SignerInfo signerInfo = verify(signerInfos[i], bytes); if (signerInfo != null) { intResult.addElement(signerInfo); } } if (intResult.size() != 0) { SignerInfo[] result = new SignerInfo[intResult.size()]; intResult.copyInto(result); return result; } return null; } /** * Returns all signerInfos which self-verify. * * @exception NoSuchAlgorithmException on unrecognized algorithms. * @exception SignatureException on signature handling errors. */ public SignerInfo[] verify() throws NoSuchAlgorithmException, SignatureException { return verify(null); } /** * Returns the version number of this PKCS7 block. */ public BigInt getVersion() { return version; } /** * Returns the message digest algorithms specified in this PKCS7 block. */ public AlgorithmId[] getDigestAlgorithmIds() { return digestAlgorithmIds; } /** * Returns the content information specified in this PKCS7 block. */ public ContentInfo getContentInfo() { return contentInfo; } /** * Returns the X.509 certificates listed in this PKCS7 block. */ public X509Certificate[] getCertificates() { return certificates; } /** * Returns the signer's information specified in this PKCS7 block. */ public SignerInfo[] getSignerInfos() { return signerInfos; } /** * Returns the X.509 certificate listed in this PKCS7 block * which has a matching serial number and Issuer name, or * null if one is not found. * * @param serial the serial number of the certificate to retrieve. * @param name the Distinguished Name of the Issuer. */ public X509Certificate getCertificate(BigInt serial, X500Name name) { for (int i = 0; i < certificates.length; i++) { X509Certificate cert = certificates[i]; X500Name thisName = (X500Name) cert.getIssuerDN(); BigInteger tmpSerial = cert.getSerialNumber(); BigInt thisSerial = new BigInt(tmpSerial); if (serial.equals(thisSerial) && name.equals(thisName)) { return cert; } } return null; } public byte[] getBytes() throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); encodeSignedData(out); return out.toByteArray(); } public String toPEMString() throws IOException { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw, true); pw.println(HEADER); pw.print(Utils.base64encode(getBytes(), true)); pw.println(FOOTER); return sw.toString(); } /** * Returns the PKCS7 block in a printable string form. */ @Override public String toString() { StringBuffer out = new StringBuffer("PKCS7 :: version: " + version + "\n"); out.append("PKCS7 :: digest AlgorithmIds: " + "\n"); for (int i = 0; i < digestAlgorithmIds.length; i++) { out.append("\t" + digestAlgorithmIds[i] + "\n"); } out.append(contentInfo + "\n"); out.append("PKCS7 :: certificates: " + "\n"); for (int i = 0; i < certificates.length; i++) { out.append("\t" + i + ". " + certificates[i] + "\n"); } out.append("PKCS7 :: signer infos: " + "\n"); for (int i = 0; i < signerInfos.length; i++) { out.append("\t" + i + ". " + signerInfos[i] + "\n"); } return out.toString(); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS8Key.java000066400000000000000000000346341412550063600265750ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.pkcs; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.Provider; import java.security.Security; import java.security.spec.InvalidKeySpecException; import java.security.spec.PKCS8EncodedKeySpec; import java.lang.reflect.InvocationTargetException; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.x509.AlgorithmId; /** * Holds a PKCS#8 key, for example a private key * * @version 1.30, 97/12/10 * @author Dave Brownell * @author Benjamin Renaud */ public class PKCS8Key implements PrivateKey { /** use serialVersionUID from JDK 1.1. for interoperability */ private static final long serialVersionUID = -3836890099307167124L; /* The algorithm information (name, parameters, etc). */ protected AlgorithmId algid; /* The key bytes, without the algorithm information */ protected byte[] key; /* The encoded for the key. */ protected byte[] encodedKey; /* The version for this key */ public static final BigInteger VERSION = BigInteger.valueOf(0); /** * Default constructor. The key constructed must have its key * and algorithm initialized before it may be used, for example * by using decode. */ public PKCS8Key() { } /** * Construct PKCS#8 subject public key from a DER value. If * the runtime environment is configured with a specific class for * this kind of key, a subclass is returned. Otherwise, a generic * PKCS8Key object is returned. * *

* This mechanism gurantees that keys (and algorithms) may be freely manipulated and transferred, without risk of * losing information. Also, when a key (or algorithm) needs some special handling, that specific need can be * accomodated. * * @param in the DER-encoded SubjectPublicKeyInfo value * @exception IOException on data format errors */ public static PKCS8Key parse(DerValue in) throws IOException { AlgorithmId algorithm; PKCS8Key subjectKey; if (in.tag != DerValue.tag_Sequence) throw new IOException("corrupt private key"); BigInteger parsedVersion = in.data.getInteger().toBigInteger(); if (!VERSION.equals(parsedVersion)) { throw new IOException("version mismatch: (supported: " + VERSION + ", parsed: " + parsedVersion); } algorithm = AlgorithmId.parse(in.data.getDerValue()); try { subjectKey = buildPKCS8Key(algorithm, in.data.getOctetString()); } catch (InvalidKeyException e) { throw new IOException("corrupt private key"); } if (in.data.available() != 0) throw new IOException("excess private key"); return subjectKey; } /** * Parse the key bits. This may be redefined by subclasses to take * advantage of structure within the key. For example, RSA public * keys encapsulate two unsigned integers (modulus and exponent) as * DER values within the key bits; Diffie-Hellman and * DSS/DSA keys encapsulate a single unsigned integer. * *

* This function is called when creating PKCS#8 SubjectPublicKeyInfo values using the PKCS8Key member functions, * such as parse and decode. * * @exception IOException if a parsing error occurs. * @exception InvalidKeyException if the key encoding is invalid. */ protected void parseKeyBits() throws IOException, InvalidKeyException { encode(); } /* * Factory interface, building the kind of key associated with this * specific algorithm ID or else returning this generic base class. * See the description above. */ public static PKCS8Key buildPKCS8Key(AlgorithmId algid, byte[] key) throws IOException, InvalidKeyException { /* * Use the algid and key parameters to produce the ASN.1 encoding * of the key, which will then be used as the input to the * key factory. */ DerOutputStream pkcs8EncodedKeyStream = new DerOutputStream(); encode(pkcs8EncodedKeyStream, algid, key); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(pkcs8EncodedKeyStream.toByteArray()); try { // Instantiate the key factory of the appropriate algorithm KeyFactory keyFac = KeyFactory.getInstance(algid.getName()); // Generate the private key PrivateKey privKey = keyFac.generatePrivate(pkcs8KeySpec); if (privKey instanceof PKCS8Key) { /* * Return specialized PKCS8Key, where the structure within the * key has been parsed */ return (PKCS8Key) privKey; } } catch (NoSuchAlgorithmException e) { // Return generic PKCS8Key with opaque key data (see below) } catch (InvalidKeySpecException e) { // Return generic PKCS8Key with opaque key data (see below) } /* * Try again using JDK1.1-style for backwards compatibility. */ String classname = ""; try { Provider sunProvider; sunProvider = Security.getProvider("SUN"); if (sunProvider == null) throw new InstantiationException(); classname = sunProvider.getProperty("PrivateKey.PKCS#8." + algid.getName()); if (classname == null) { throw new InstantiationException(); } Class keyClass = Class.forName(classname); Object inst; PKCS8Key result; inst = keyClass.getConstructor().newInstance(); if (inst instanceof PKCS8Key) { result = (PKCS8Key) inst; result.algid = algid; result.key = key; result.parseKeyBits(); return result; } } catch (ClassNotFoundException e) { } catch (InstantiationException e) { } catch (IllegalAccessException e) { throw new IOException("IllegalAccessException : " + e.getMessage(), e); } catch (NoSuchMethodException e) { } catch (InvocationTargetException e) { throw new IOException("InvocationTargetException : " + e.getMessage(), e); } PKCS8Key result = new PKCS8Key(); result.algid = algid; result.key = key; return result; } /** * Returns the algorithm to be used with this key. */ @Override public String getAlgorithm() { return algid.getName(); } /** * Returns the algorithm ID to be used with this key. */ public AlgorithmId getAlgorithmId() { return algid; } /** * PKCS#8 sequence on the DER output stream. */ public final void encode(DerOutputStream out) throws IOException { encode(out, this.algid, this.key); } /** * Returns the DER-encoded form of the key as a byte array. */ @Override public synchronized byte[] getEncoded() { byte[] result = null; try { result = encode(); } catch (InvalidKeyException e) { } return result; } /** * Returns the format for this key: "PKCS#8" */ @Override public String getFormat() { return "PKCS#8"; } /** * Returns the DER-encoded form of the key as a byte array. * * @exception InvalidKeyException if an encoding error occurs. */ public byte[] encode() throws InvalidKeyException { if (encodedKey == null) { try { DerOutputStream out; out = new DerOutputStream(); encode(out); encodedKey = out.toByteArray(); } catch (IOException e) { throw new InvalidKeyException("IOException : " + e.getMessage()); } } return copyEncodedKey(encodedKey); } /* * Returns a printable representation of the key */ @Override public String toString() { org.mozilla.jss.netscape.security.util.PrettyPrintFormat pp = new org.mozilla.jss.netscape.security.util.PrettyPrintFormat(" ", 20); String keybits = pp.toHexString(key); return "algorithm = " + algid.toString() + ", unparsed keybits = \n" + keybits; } /** * Initialize an PKCS8Key object from an input stream. The data * on that input stream must be encoded using DER, obeying the * PKCS#8 format: a sequence consisting of a version, an algorithm * ID and a bit string which holds the key. (That bit string is * often used to encapsulate another DER encoded sequence.) * *

* Subclasses should not normally redefine this method; they should instead provide a parseKeyBits * method to parse any fields inside the key member. * * @param in an input stream with a DER-encoded PKCS#8 * SubjectPublicKeyInfo value * * @exception InvalidKeyException if a parsing error occurs. */ public void decode(InputStream in) throws InvalidKeyException { DerValue val; try { val = new DerValue(in); if (val.tag != DerValue.tag_Sequence) throw new InvalidKeyException("invalid key format"); BigInteger version = val.data.getInteger().toBigInteger(); if (!version.equals(PKCS8Key.VERSION)) { throw new IOException("version mismatch: (supported: " + PKCS8Key.VERSION + ", parsed: " + version); } algid = AlgorithmId.parse(val.data.getDerValue()); key = val.data.getOctetString(); parseKeyBits(); if (val.data.available() != 0) throw new InvalidKeyException("excess key data"); } catch (IOException e) { // e.printStackTrace (); throw new InvalidKeyException("IOException : " + e.getMessage()); } } public void decode(byte[] encodedKey) throws InvalidKeyException { decode(new ByteArrayInputStream(encodedKey)); } /** * Serialization write ... PKCS#8 keys serialize as * themselves, and they're parsed when they get read back. */ private void writeObject(java.io.ObjectOutputStream stream) throws IOException { stream.write(getEncoded()); } /** * Serialization read ... PKCS#8 keys serialize as * themselves, and they're parsed when they get read back. */ private void readObject(ObjectInputStream stream) throws IOException { try { decode(stream); } catch (InvalidKeyException e) { e.printStackTrace(); throw new IOException("deserialized key is invalid: " + e.getMessage()); } } /* * Make a copy of the encoded key. */ private byte[] copyEncodedKey(byte[] encodedKey) { int len = encodedKey.length; byte[] copy = new byte[len]; System.arraycopy(encodedKey, 0, copy, 0, len); return copy; } /* * Produce PKCS#8 encoding from algorithm id and key material. */ static void encode(DerOutputStream out, AlgorithmId algid, byte[] key) throws IOException { DerOutputStream tmp = new DerOutputStream(); tmp.putInteger(new BigInt(VERSION.toByteArray())); algid.encode(tmp); tmp.putOctetString(key); out.write(DerValue.tag_Sequence, tmp); } /** * Compares two private keys. This returns false if the object with which * to compare is not of type Key. * Otherwise, the encoding of this key object is compared with the * encoding of the given key object. * * @param object the object with which to compare * @return true if this key has the same encoding as the * object argument; false otherwise. */ @Override public boolean equals(Object object) { if (this == object) { return true; } if (object instanceof Key) { // this encoding byte[] b1; if (encodedKey != null) { b1 = encodedKey; } else { b1 = getEncoded(); } // that encoding byte[] b2 = ((Key) object).getEncoded(); // do the comparison int i; if (b1.length != b2.length) return false; for (i = 0; i < b1.length; i++) { if (b1[i] != b2[i]) { return false; } } return true; } return false; } /** * Calculates a hash code value for this object. Objects * which are equal will also have the same hashcode. */ @Override public int hashCode() { int retval = 0; byte[] b1 = getEncoded(); for (int i = 1; i < b1.length; i++) { retval += b1[i] * i; } return (retval); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS9Attribute.java000066400000000000000000001060741412550063600300070ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.pkcs; import java.io.IOException; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Date; import java.util.Hashtable; import org.mozilla.jss.netscape.security.util.DerEncoder; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; import org.mozilla.jss.netscape.security.x509.CertificateExtensions; /** * Class supporting any PKCS9 attribute except * ExtendedCertificateAttribute. Supports DER decoding and access to * attribute values, but not DER encoding or setting of values. * * @version 1.2 97/12/10 * @author Douglas Hoover */ public class PKCS9Attribute implements DerEncoder { /* * OIDs of PKCS #9 attribute types. */ private static final String RSADSI_str = "1.2.840.113549"; private static final String PKCS_str = RSADSI_str + ".1"; private static final String PKCS9_str = PKCS_str + ".9"; /** * Array of attribute OIDs defined in PKCS9, by number. */ static final ObjectIdentifier[] PKCS9_OIDS = //new ObjectIdentifier[10]; // There are some Obsolete(?) attribute identifiers. // This is mainly for extensionRequest (14) in pkcs10. // We just add the other 4 as by products. new ObjectIdentifier[15]; static { // static initializer for PKCS9_OIDS for (int i = 1; i < PKCS9_OIDS.length; i++) { PKCS9_OIDS[i] = new ObjectIdentifier(PKCS9_str + "." + i); } } public static final ObjectIdentifier EMAIL_ADDRESS_OID = PKCS9_OIDS[1]; public static final ObjectIdentifier UNSTRUCTURED_NAME_OID = PKCS9_OIDS[2]; public static final ObjectIdentifier CONTENT_TYPE_OID = PKCS9_OIDS[3]; public static final ObjectIdentifier MESSAGE_DIGEST_OID = PKCS9_OIDS[4]; public static final ObjectIdentifier SIGNING_TIME_OID = PKCS9_OIDS[5]; public static final ObjectIdentifier COUNTERSIGNATURE_OID = PKCS9_OIDS[6]; public static final ObjectIdentifier CHALLENGE_PASSWORD_OID = PKCS9_OIDS[7]; public static final ObjectIdentifier UNSTRUCTURED_ADDRESS_OID = PKCS9_OIDS[8]; public static final ObjectIdentifier EXTENDED_CERTIFICATE_ATTRIBUTES_OID = PKCS9_OIDS[9]; public static final ObjectIdentifier ISSUER_AND_SERIALNUMBER_OID = PKCS9_OIDS[10]; public static final ObjectIdentifier PASSWORD_CHECK_OID = PKCS9_OIDS[11]; public static final ObjectIdentifier PUBLIC_KEY_OID = PKCS9_OIDS[12]; public static final ObjectIdentifier SIGNING_DESCRIPTION_OID = PKCS9_OIDS[13]; public static final ObjectIdentifier EXTENSION_REQUEST_OID = PKCS9_OIDS[14]; public static final String EMAIL_ADDRESS_STR = "EmailAddress"; public static final String UNSTRUCTURED_NAME_STR = "UnstructuredName"; public static final String CONTENT_TYPE_STR = "ContentType"; public static final String MESSAGE_DIGEST_STR = "MessageDigest"; public static final String SIGNING_TIME_STR = "SigningTime"; public static final String COUNTERSIGNATURE_STR = "Countersignature"; public static final String CHALLENGE_PASSWORD_STR = "ChallengePassword"; public static final String UNSTRUCTURED_ADDRESS_STR = "UnstructuredAddress"; public static final String EXTENDED_CERTIFICATE_ATTRIBUTES_STR = "ExtendedCertificateAttributes"; public static final String ISSUER_AND_SERIALNUMBER_STR = "IssuerAndSerialNumber"; public static final String PASSWORD_CHECK_STR = "PasswordCheck"; public static final String PUBLIC_KEY_STR = "PublicKey"; public static final String SIGNING_DESCRIPTION_STR = "SigningDescription"; public static final String EXTENSION_REQUEST_STR = "ExtensionRequest"; /** * Hashtable mapping names and variant names of supported * attributes to their OIDs. This table contains all name forms * that occur in PKCS9, in lower case. */ private static final Hashtable NAME_OID_TABLE = new Hashtable( 28); static { // static initializer for PCKS9_NAMES NAME_OID_TABLE.put("emailaddress", PKCS9_OIDS[1]); NAME_OID_TABLE.put("unstructuredname", PKCS9_OIDS[2]); NAME_OID_TABLE.put("contenttype", PKCS9_OIDS[3]); NAME_OID_TABLE.put("messagedigest", PKCS9_OIDS[4]); NAME_OID_TABLE.put("signingtime", PKCS9_OIDS[5]); NAME_OID_TABLE.put("countersignature", PKCS9_OIDS[6]); NAME_OID_TABLE.put("challengepassword", PKCS9_OIDS[7]); NAME_OID_TABLE.put("unstructuredaddress", PKCS9_OIDS[8]); NAME_OID_TABLE.put("extendedcertificateattributes", PKCS9_OIDS[9]); NAME_OID_TABLE.put("issuerandserialNumber", PKCS9_OIDS[10]); NAME_OID_TABLE.put("passwordcheck", PKCS9_OIDS[11]); NAME_OID_TABLE.put("publickey", PKCS9_OIDS[12]); NAME_OID_TABLE.put("signingdescription", PKCS9_OIDS[13]); NAME_OID_TABLE.put("extensionrequest", PKCS9_OIDS[14]); }; /** * Hashtable mapping attribute OIDs defined in PKCS9 to the * corresponding attribute value type. */ private static final Hashtable OID_NAME_TABLE = new Hashtable( 14); static { OID_NAME_TABLE.put(PKCS9_OIDS[1], EMAIL_ADDRESS_STR); OID_NAME_TABLE.put(PKCS9_OIDS[2], UNSTRUCTURED_NAME_STR); OID_NAME_TABLE.put(PKCS9_OIDS[3], CONTENT_TYPE_STR); OID_NAME_TABLE.put(PKCS9_OIDS[4], MESSAGE_DIGEST_STR); OID_NAME_TABLE.put(PKCS9_OIDS[5], SIGNING_TIME_STR); OID_NAME_TABLE.put(PKCS9_OIDS[6], COUNTERSIGNATURE_STR); OID_NAME_TABLE.put(PKCS9_OIDS[7], CHALLENGE_PASSWORD_STR); OID_NAME_TABLE.put(PKCS9_OIDS[8], UNSTRUCTURED_ADDRESS_STR); OID_NAME_TABLE.put(PKCS9_OIDS[9], EXTENDED_CERTIFICATE_ATTRIBUTES_STR); OID_NAME_TABLE.put(PKCS9_OIDS[10], ISSUER_AND_SERIALNUMBER_STR); OID_NAME_TABLE.put(PKCS9_OIDS[11], PASSWORD_CHECK_STR); OID_NAME_TABLE.put(PKCS9_OIDS[12], PUBLIC_KEY_STR); OID_NAME_TABLE.put(PKCS9_OIDS[13], SIGNING_DESCRIPTION_STR); OID_NAME_TABLE.put(PKCS9_OIDS[14], EXTENSION_REQUEST_STR); } /** * Acceptable ASN.1 tags for DER encodings of values of PKCS9 * attributes, by index in PKCS9_OIDS. * Sets of acceptable tags are represented as arrays. */ private static final Byte[][] PKCS9_VALUE_TAGS = { null, { Byte.valueOf(DerValue.tag_IA5String) }, // EMailAddress { Byte.valueOf(DerValue.tag_IA5String) }, // UnstructuredName { Byte.valueOf(DerValue.tag_ObjectId) }, // ContentType { Byte.valueOf(DerValue.tag_OctetString) }, // MessageDigest { Byte.valueOf(DerValue.tag_UtcTime) }, // SigningTime { Byte.valueOf(DerValue.tag_Sequence) }, // Countersignature { Byte.valueOf(DerValue.tag_PrintableString), Byte.valueOf(DerValue.tag_T61String) }, // ChallengePassword { Byte.valueOf(DerValue.tag_PrintableString), Byte.valueOf(DerValue.tag_T61String) }, // UnstructuredAddress { Byte.valueOf(DerValue.tag_SetOf) }, // ExtendedCertificateAttributes null, //IssuerAndSerialNumber null, //PasswordCheck null, //PublicKey null, //SigningDescription { Byte.valueOf(DerValue.tag_Sequence) } //ExtensionRequest }; /** * Class types required for values for a given PKCS9 * attribute type. * *

* The following table shows the correspondence between attribute types and value component classes. * *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
OIDAttribute Type NameKindValue Class
1.2.840.113549.1.9.1EmailAddressMultiple-valuedString[]
1.2.840.113549.1.9.2UnstructuredNameMultiple-valuedString
1.2.840.113549.1.9.3ContentTypeSingle-valuedObjectIdentifier
1.2.840.113549.1.9.4MessageDigestSingle-valuedbyte[]
1.2.840.113549.1.9.5SigningTimeSingle-valuedDate
1.2.840.113549.1.9.6CountersignatureMultiple-valuedSignerInfo
1.2.840.113549.1.9.7ChallengePasswordSingle-valuedString
1.2.840.113549.1.9.8UnstructuredAddressSingle-valuedString
1.2.840.113549.1.9.9ExtendedCertificateAttributesMultiple-valued(not supported)
1.2.840.113549.1.9.10IssuerAndSerialNumberSingle-valued(not supported)
1.2.840.113549.1.9.11PasswordCheckSingle-valued(not supported)
1.2.840.113549.1.9.12PublicKeySingle-valued(not supported)
1.2.840.113549.1.9.13SigningDescriptionSingle-valued(not supported)
1.2.840.113549.1.9.14ExtensionRequestSingle-valuedSequence
*/ private static final Class[] VALUE_CLASSES = new Class[15]; static { VALUE_CLASSES[0] = null; // not used VALUE_CLASSES[1] = String[].class; // EMailAddress VALUE_CLASSES[2] = String[].class; // UnstructuredName VALUE_CLASSES[3] = ObjectIdentifier.class; // ContentType VALUE_CLASSES[4] = byte[].class; // MessageDigest (byte[]) VALUE_CLASSES[5] = Date.class; // SigningTime VALUE_CLASSES[6] = SignerInfo[].class; // Countersignature VALUE_CLASSES[7] = String.class; // ChallengePassword VALUE_CLASSES[8] = String[].class; // UnstructuredAddress VALUE_CLASSES[9] = null; // ExtendedCertificateAttributes VALUE_CLASSES[10] = null; // IssuerAndSerialNumber VALUE_CLASSES[11] = null; // PasswordCheck VALUE_CLASSES[12] = null; // PublicKey VALUE_CLASSES[13] = null; // SigningDescription VALUE_CLASSES[14] = CertificateExtensions.class; // ExtensionRequest } /** * Array indicating which PKCS9 attributes are single-valued, * by index in PKCS9_OIDS. */ private static final boolean[] SINGLE_VALUED = { false, false, // EMailAddress false, // UnstructuredName true, // ContentType true, // MessageDigest true, // SigningTime false, // Countersignature true, // ChallengePassword false, // UnstructuredAddress false, // ExtendedCertificateAttributes true, // IssuerAndSerialNumber true, // PasswordCheck true, // PublicKey true, // SigningDescription true // ExtensionRequest }; /** * The OID of this attribute is PKCS9_OIDS[index]. */ private int index; /** * Value set of this attribute. Its class is given by VALUE_CLASSES[index]. */ private Object value; /** * Construct an attribute object from the attribute's OID and * value. If the attribute is single-valued, provide only one * value. If the attribute is * multiple-valued, provide an array containing all the values. * Arrays of length zero are accepted, though probably useless. * *

* The following table gives the class that value must have for a given attribute. * *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
value
OIDAttribute Type NameKindValue Class
1.2.840.113549.1.9.1EmailAddressMultiple-valuedString[]
1.2.840.113549.1.9.2UnstructuredNameMultiple-valuedString[]
1.2.840.113549.1.9.3ContentTypeSingle-valuedObjectIdentifier
1.2.840.113549.1.9.4MessageDigestSingle-valuedbyte[]
1.2.840.113549.1.9.5SigningTimeSingle-valuedDate
1.2.840.113549.1.9.6CountersignatureMultiple-valuedSignerInfo[]
1.2.840.113549.1.9.7ChallengePasswordSingle-valuedString
1.2.840.113549.1.9.8UnstructuredAddressSingle-valuedString[]
1.2.840.113549.1.9.9ExtendedCertificateAttributesMultiple-valued(not supported)
1.2.840.113549.1.9.10IssuerAndSerialNumberSingle-valued(not supported)
1.2.840.113549.1.9.11PasswordCheckSingle-valued(not supported)
1.2.840.113549.1.9.12PublicKeySingle-valued(not supported)
1.2.840.113549.1.9.13SigningDescriptionSingle-valued(not supported)
1.2.840.113549.1.9.14ExtensionRequestSingle-valuedSequence
*/ public PKCS9Attribute(ObjectIdentifier oid, Object value) throws IllegalArgumentException { init(oid, value); } /** * Construct an attribute object from the attribute's name and * value. If the attribute is single-valued, provide only one * value. If the attribute is * multiple-valued, provide an array containing all the values. * Arrays of length zero are accepted, though probably useless. * *

* The following table gives the class that value must have for a given attribute. Reasonable variants * of these attributes are accepted; in particular, case does not matter. * *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
value
OIDAttribute Type NameKindValue Class
1.2.840.113549.1.9.1EmailAddressMultiple-valuedString[]
1.2.840.113549.1.9.2UnstructuredNameMultiple-valuedString[]
1.2.840.113549.1.9.3ContentTypeSingle-valuedObjectIdentifier
1.2.840.113549.1.9.4MessageDigestSingle-valuedbyte[]
1.2.840.113549.1.9.5SigningTimeSingle-valuedDate
1.2.840.113549.1.9.6CountersignatureMultiple-valuedSignerInfo[]
1.2.840.113549.1.9.7ChallengePasswordSingle-valuedString
1.2.840.113549.1.9.8UnstructuredAddressSingle-valuedString[]
1.2.840.113549.1.9.9ExtendedCertificateAttributesMultiple-valued(not supported)
1.2.840.113549.1.9.10IssuerAndSerialNumberSingle-valued(not supported)
1.2.840.113549.1.9.11PasswordCheckSingle-valued(not supported)
1.2.840.113549.1.9.12PublicKeySingle-valued(not supported)
1.2.840.113549.1.9.13SigningDescriptionSingle-valued(not supported)
1.2.840.113549.1.9.14ExtensionRequestSingle-valuedSequence
* * @exception IllegalArgumentException * if the name is not recognized of the value has the wrong type. */ public PKCS9Attribute(String name, Object value) throws IllegalArgumentException { ObjectIdentifier oid = getOID(name); if (oid == null) throw new IllegalArgumentException( "Unrecognized attribute name " + name + " constructing PKCS9Attribute."); init(oid, value); } private void init(ObjectIdentifier oid, Object value) throws IllegalArgumentException { index = indexOf(oid, PKCS9_OIDS, 1); if (index == -1) throw new IllegalArgumentException( "Unsupported OID " + oid + " constructing PKCS9Attribute."); if (!VALUE_CLASSES[index].isInstance(value)) throw new IllegalArgumentException( "Wrong value class " + " for attribute " + oid + " constructing PKCS9Attribute; was " + value.getClass().toString() + ", should be " + VALUE_CLASSES[index].toString()); this.value = value; } /** * Construct a PKCS9Attribute from its encoding on an input * stream. * * @exception IOException on parsing error. */ public PKCS9Attribute(DerValue derVal) throws IOException { decode(derVal); } /** * Decode a PKCS9 attribute. * * @param val * the DerValue representing the DER encoding of the attribute. */ private void decode(DerValue derVal) throws IOException { DerInputStream derIn = new DerInputStream(derVal.toByteArray()); DerValue[] val = derIn.getSequence(2); if (derIn.available() != 0) throw new IOException("Excess data parsing PKCS9Attribute"); if (val.length != 2) throw new IOException("PKCS9Attribute doesn't have two components"); DerValue[] elems; // get the oid ObjectIdentifier oid = val[0].getOID(); index = indexOf(oid, PKCS9_OIDS, 1); Byte tag; if (index == -1) throw new IOException("Invalid OID for PKCS9 attribute: " + oid); elems = new DerInputStream(val[1].toByteArray()).getSet(1); // check single valued have only one value if (SINGLE_VALUED[index] && elems.length > 1) throwSingleValuedException(); // check for illegal element tags for (int i = 0; i < elems.length; i++) { tag = Byte.valueOf(elems[i].tag); if (indexOf(tag, PKCS9_VALUE_TAGS[index], 0) == -1) throwTagException(tag); } switch (index) { case 1: // email address case 2: // unstructured name case 8: // unstructured address { // open scope String[] values = new String[elems.length]; for (int i = 0; i < elems.length; i++) values[i] = elems[i].getAsString(); value = values; } // close scope break; case 3: // content type value = elems[0].getOID(); break; case 4: // message digest value = elems[0].getOctetString(); break; case 5: // signing time value = (new DerInputStream(elems[0].toByteArray())).getUTCTime(); break; case 6: // countersignature { // open scope SignerInfo[] values = new SignerInfo[elems.length]; for (int i = 0; i < elems.length; i++) values[i] = new SignerInfo(elems[i].toDerInputStream()); value = values; } // close scope break; case 7: // challenge password value = elems[0].getAsString(); break; case 9: // extended-certificate attribute -- not // supported throw new IOException("PKCS9 extended-certificate " + "attribute not supported."); case 10: // IssuerAndSerialNumber attribute -- not // supported throw new IOException("PKCS9 IssuerAndSerialNumber " + "attribute not supported."); case 11: // passwordCheck attribute -- not // supported throw new IOException("PKCS9 passwordCheck " + "attribute not supported."); case 12: // PublicKey attribute -- not // supported throw new IOException("PKCS9 PublicKey " + "attribute not supported."); case 13: // SigningDescription attribute -- not // supported throw new IOException("PKCS9 SigningDescription " + "attribute not supported."); case 14: // ExtensionRequest attribute value = new CertificateExtensions(elems[0].toDerInputStream()); // break unnecessary default: // can't happen } } /** * Write the DER encoding of this attribute to an output stream. * *

* N.B.: This method always encodes values of ChallengePassword and UnstructuredAddress attributes as ASN.1 * PrintableStrings, without checking whether they should be encoded as T61Strings. */ @Override public void derEncode(OutputStream out) throws IOException { try (DerOutputStream temp = new DerOutputStream(); DerOutputStream temp2 = new DerOutputStream(); DerOutputStream derOut = new DerOutputStream()) { temp.putOID(getOID()); switch (index) { case 1: // email address case 2: // unstructured name { // open scope String[] values = (String[]) value; DerOutputStream[] temps = new DerOutputStream[values.length]; for (int i = 0; i < values.length; i++) { temps[i] = new DerOutputStream(); temps[i].putIA5String(values[i]); } temp.putOrderedSetOf(DerValue.tag_Set, temps); } // close scope break; case 3: // content type { temp2.putOID((ObjectIdentifier) value); temp.write(DerValue.tag_Set, temp2.toByteArray()); } break; case 4: // message digest { temp2.putOctetString((byte[]) value); temp.write(DerValue.tag_Set, temp2.toByteArray()); } break; case 5: // signing time { temp2.putUTCTime((Date) value); temp.write(DerValue.tag_Set, temp2.toByteArray()); } break; case 6: // countersignature temp.putOrderedSetOf(DerValue.tag_Set, (DerEncoder[]) value); break; case 7: // challenge password { temp2.putPrintableString((String) value); temp.write(DerValue.tag_Set, temp2.toByteArray()); } break; case 8: // unstructured address { // open scope String[] values = (String[]) value; DerOutputStream[] temps = new DerOutputStream[values.length]; for (int i = 0; i < values.length; i++) { temps[i] = new DerOutputStream(); temps[i].putPrintableString(values[i]); } temp.putOrderedSetOf(DerValue.tag_Set, temps); } // close scope break; case 9: // extended-certificate attribute -- not // supported throw new IOException("PKCS9 extended-certificate " + "attribute not supported."); case 10: // IssuerAndSerialNumber attribute -- not // supported throw new IOException("PKCS9 IssuerAndSerialNumber " + "attribute not supported."); case 11: // passwordCheck attribute -- not // supported throw new IOException("PKCS9 passwordCheck " + "attribute not supported."); case 12: // PublicKey attribute -- not // supported throw new IOException("PKCS9 PublicKey " + "attribute not supported."); case 13: // SigningDescription attribute -- not // supported throw new IOException("PKCS9 SigningDescription " + "attribute not supported."); case 14: // ExtensionRequest attribute try { //temp2.putSequence((CertificateExtensions) value); ((CertificateExtensions) value).encode(temp2); temp.write(DerValue.tag_Sequence, temp2.toByteArray()); } catch (CertificateException e) { throw new IOException("PKCS9 extension attributes not encoded"); } // break unnecessary default: // can't happen } derOut.write(DerValue.tag_Sequence, temp.toByteArray()); out.write(derOut.toByteArray()); } } /** * Get the value of this attribute. If the attribute is * single-valued, return just the one value. If the attribute is * multiple-valued, return an array containing all the values. * It is possible for this array to be of length 0. * *

* The following table gives the class of the value returned, depending on the type of this attribute. * *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
value
OIDAttribute Type NameKindValue Class
1.2.840.113549.1.9.1EmailAddressMultiple-valuedString[]
1.2.840.113549.1.9.2UnstructuredNameMultiple-valuedString[]
1.2.840.113549.1.9.3ContentTypeSingle-valuedObjectIdentifier
1.2.840.113549.1.9.4MessageDigestSingle-valuedbyte[]
1.2.840.113549.1.9.5SigningTimeSingle-valuedDate
1.2.840.113549.1.9.6CountersignatureMultiple-valuedSignerInfo[]
1.2.840.113549.1.9.7ChallengePasswordSingle-valuedString
1.2.840.113549.1.9.8UnstructuredAddressSingle-valuedString[]
1.2.840.113549.1.9.9ExtendedCertificateAttributesMultiple-valued(not supported)
1.2.840.113549.1.9.10IssuerAndSerialNumberSingle-valued(not supported)
1.2.840.113549.1.9.11PasswordCheckSingle-valued(not supported)
1.2.840.113549.1.9.12PublicKeySingle-valued(not supported)
1.2.840.113549.1.9.13SigningDescriptionSingle-valued(not supported)
1.2.840.113549.1.9.14ExtensionRequestSingle-valuedSequence
* */ public Object getValue() { return value; } /** * Show whether this attribute is single-valued. */ public boolean isSingleValued() { return SINGLE_VALUED[index]; } /** * Return the OID of this attribute. */ public ObjectIdentifier getOID() { return PKCS9_OIDS[index]; } /** * Return the name of this attribute. */ public String getName() { return OID_NAME_TABLE.get(PKCS9_OIDS[index]); } /** * Return the OID for a given attribute name or null if we don't recognize * the name. */ public static ObjectIdentifier getOID(String name) { return NAME_OID_TABLE.get(name.toLowerCase()); } /** * Return the attribute name for a given OID or null if we don't recognize * the oid. */ public static String getName(ObjectIdentifier oid) { return OID_NAME_TABLE.get(oid); } /** * Returns a string representation of this attribute. */ @Override public String toString() { StringBuffer buf = new StringBuffer(100); buf.append("["); buf.append(OID_NAME_TABLE.get(PKCS9_OIDS[index])); buf.append(": "); if (SINGLE_VALUED[index]) { if (value instanceof byte[]) { // special case for octet string org.mozilla.jss.netscape.security.util.PrettyPrintFormat pp = new org.mozilla.jss.netscape.security.util.PrettyPrintFormat(" ", 20); String valuebits = pp.toHexString(((byte[]) value)); buf.append(valuebits); } else { buf.append(value.toString()); } buf.append("]"); return buf.toString(); } else { // multiple-valued boolean first = true; Object[] values = (Object[]) value; for (int j = 0; j < values.length; j++) { if (first) first = false; else buf.append(", "); buf.append(values[j].toString()); } return buf.toString(); } } /** * Beginning the search at start, find the first * index i such that a[i] = obj. * * @return the index, if found, and -1 otherwise. */ static int indexOf(Object obj, Object[] a, int start) { for (int i = start; i < a.length; i++) { if (obj.equals(a[i])) return i; } return -1; } /** * Throw an exception when there are multiple values for * a single-valued attribute. */ private void throwSingleValuedException() throws IOException { throw new IOException("Single-value attribute " + getOID() + " (" + getName() + ")" + " has multiple values."); } /** * Throw an exception when the tag on a value encoding is * wrong for the attribute whose value it is. */ private void throwTagException(Byte tag) throws IOException { Byte[] expectedTags = PKCS9_VALUE_TAGS[index]; StringBuffer msg = new StringBuffer(100); msg.append("Value of attribute "); msg.append(getOID().toString()); msg.append(" ("); msg.append(getName()); msg.append(") has wrong tag: "); msg.append(tag.toString()); msg.append(". Expected tags: "); msg.append(expectedTags[0].toString()); for (int i = 1; i < expectedTags.length; i++) { msg.append(", "); msg.append(expectedTags[i].toString()); } msg.append("."); throw new IOException(msg.toString()); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS9Attributes.java000066400000000000000000000235711412550063600301720ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.pkcs; import java.io.IOException; import java.io.OutputStream; import java.util.Hashtable; import org.mozilla.jss.netscape.security.util.DerEncoder; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** * A set of attributes of class PKCS9Attribute. * * @version 1.2 97/12/10 * @author Douglas Hoover */ public class PKCS9Attributes { /** * Attributes in this set indexed by OID. */ private final Hashtable attributes = new Hashtable(3); /** * The keys of this hashtable are the OIDs of permitted attributes. */ private final Hashtable permittedAttributes; /** * The DER encoding of this attribute set. The tag byte must be * DerValue.tag_SetOf. */ private final byte[] derEncoding; /** * Construct a set of PKCS9 Attributes from its * DER encoding on a DerInputStream, accepting only attributes * with OIDs on the given * list. If the array is null, accept all attributes supported by * class PKCS9Attribute. * * @param permittedAttributes * Array of attribute OIDs that will be accepted. * @param in * the contents of the DER encoding of the attribute set. * * @exception IOException * on i/o error, encoding syntax error, unacceptable or * unsupported attribute, or duplicate attribute. * * @see PKCS9Attribute */ public PKCS9Attributes(ObjectIdentifier[] permittedAttributes, DerInputStream in) throws IOException { if (permittedAttributes != null) { this.permittedAttributes = new Hashtable(permittedAttributes.length); for (int i = 0; i < permittedAttributes.length; i++) this.permittedAttributes.put(permittedAttributes[i], permittedAttributes[i]); } else { this.permittedAttributes = null; } // derEncoding initialized in decode() derEncoding = decode(in); } /** * Construct a set of PKCS9 Attributes from its contents of its * DER encoding on a DerInputStream. Accept all attributes * supported by class PKCS9Attribute. * * @exception IOException * on i/o error, encoding syntax error, or unsupported or * duplicate attribute. * * @see PKCS9Attribute */ public PKCS9Attributes(DerInputStream in) throws IOException { // anything goes // derEncoding initialized in decode() derEncoding = decode(in); permittedAttributes = null; } /** * Construct a set of PKCS9 Attributes from the given array of * PCK9 attributes. * DER encoding on a DerInputStream. All attributes in attribs must be * supported by class PKCS9Attribute. * * @exception IOException * on i/o error, encoding syntax error, or unsupported or * duplicate attribute. * * @see PKCS9Attribute */ public PKCS9Attributes(PKCS9Attribute[] attribs) throws IllegalArgumentException, IOException { ObjectIdentifier oid; for (int i = 0; i < attribs.length; i++) { oid = attribs[i].getOID(); if (attributes.containsKey(oid)) throw new IllegalArgumentException( "PKCSAttribute " + attribs[i].getOID() + " duplicated while constructing " + "PKCS9Attributes."); attributes.put(oid, attribs[i]); } derEncoding = generateDerEncoding(); permittedAttributes = null; } /** * Decode this set of PKCS9 attribute set from the contents of its * DER encoding. * * @param buf * the contents of the DER encoding of the attribute set. * * @exception IOException * on i/o error, encoding syntax error, unacceptable or * unsupported attribute, or duplicate attribute. */ private byte[] decode(DerInputStream in) throws IOException { DerValue val = in.getDerValue(); // save the DER encoding with its proper tag byte. byte[] derEncoding = val.toByteArray(); derEncoding[0] = DerValue.tag_SetOf; DerInputStream derIn = new DerInputStream(derEncoding); DerValue[] derVals = derIn.getSet(3, true); PKCS9Attribute attrib; ObjectIdentifier oid; for (int i = 0; i < derVals.length; i++) { attrib = new PKCS9Attribute(derVals[i]); oid = attrib.getOID(); if (attributes.get(oid) != null) throw new IOException("Duplicate PKCS9 attribute: " + oid); if (permittedAttributes != null && !permittedAttributes.containsKey(oid)) throw new IOException("Attribute " + oid + " not permitted in this attribute set"); attributes.put(oid, attrib); } return derEncoding; } /** * Put the DER encoding of this PKCS9 attribute set on an * DerOutputStream, tagged with the given implicit tag. * * @param tag the implicit tag to use in the DER encoding. * @param out the output stream on which to put the DER encoding. * * @exception IOException on output error. */ public void encode(byte tag, OutputStream out) throws IOException { out.write(tag); out.write(derEncoding, 1, derEncoding.length - 1); } private byte[] generateDerEncoding() throws IOException { try (DerOutputStream out = new DerOutputStream()) { Object[] attribVals = attributes.values().toArray(); out.putOrderedSetOf(DerValue.tag_SetOf, castToDerEncoder(attribVals)); return out.toByteArray(); } } /** * Return the DER encoding of this attribute set, tagged with * DerValue.tag_SetOf. */ public byte[] getDerEncoding() throws IOException { return derEncoding.clone(); } /** * Get an attribute from this set. */ public PKCS9Attribute getAttribute(ObjectIdentifier oid) { return attributes.get(oid); } /** * Get an attribute from this set. */ public PKCS9Attribute getAttribute(String name) { return attributes.get(PKCS9Attribute.getOID(name)); } /** * Get an array of all attributes in this set, in order of OID. */ public PKCS9Attribute[] getAttributes() { PKCS9Attribute[] attribs = new PKCS9Attribute[attributes.size()]; int j = 0; for (int i = 1; i < PKCS9Attribute.PKCS9_OIDS.length && j < attribs.length; i++) { attribs[j] = getAttribute(PKCS9Attribute.PKCS9_OIDS[i]); if (attribs[j] != null) j++; } return attribs; } /** * Get an attribute value by OID. */ public Object getAttributeValue(ObjectIdentifier oid) throws IOException { try { Object value = getAttribute(oid).getValue(); return value; } catch (NullPointerException ex) { throw new IOException("No value found for attribute " + oid); } } /** * Get an attribute value by type name. */ public Object getAttributeValue(String name) throws IOException { ObjectIdentifier oid = PKCS9Attribute.getOID(name); if (oid == null) throw new IOException("Attribute name " + name + " not recognized or not supported."); return getAttributeValue(oid); } /** * Returns the PKCS9 block in a printable string form. */ @Override public String toString() { StringBuffer buf = new StringBuffer(200); buf.append("PKCS9 Attributes: [\n\t"); PKCS9Attribute value; boolean first = true; for (int i = 1; i < PKCS9Attribute.PKCS9_OIDS.length; i++) { value = getAttribute(PKCS9Attribute.PKCS9_OIDS[i]); if (value == null) continue; // we have a value; print it if (first) first = false; else buf.append(";\n\t"); buf.append(value.toString()); } buf.append("\n\t] (end PKCS9 Attributes)"); return buf.toString(); } /** * Cast an object array whose components are DerEncoders to DerEncoder[]. */ static DerEncoder[] castToDerEncoder(Object[] objs) { DerEncoder[] encoders = new DerEncoder[objs.length]; for (int i = 0; i < encoders.length; i++) encoders[i] = (DerEncoder) objs[i]; return encoders; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/pkcs/ParsingException.java000066400000000000000000000024361412550063600305510ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.pkcs; import java.io.IOException; public class ParsingException extends IOException { /** * */ private static final long serialVersionUID = -8135726194372647410L; public ParsingException() { super(); } public ParsingException(String mesg) { super(mesg); } public ParsingException(String mesg, Throwable cause) { super(mesg, cause); } public ParsingException(Throwable cause) { super(cause); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/pkcs/SignerInfo.java000066400000000000000000000276361412550063600273430ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.pkcs; import java.io.IOException; import java.io.OutputStream; import java.security.InvalidKeyException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.security.cert.X509Certificate; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerEncoder; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; import org.mozilla.jss.netscape.security.x509.AlgorithmId; import org.mozilla.jss.netscape.security.x509.X500Name; /** * A SignerInfo, as defined in PKCS#7's signedData type. * * @author Benjamin Renaud * @version 1.27 97/12/10 */ public class SignerInfo implements DerEncoder { BigInt version; X500Name issuerName; BigInt certificateSerialNumber; AlgorithmId digestAlgorithmId; AlgorithmId digestEncryptionAlgorithmId; byte[] encryptedDigest; PKCS9Attributes authenticatedAttributes; PKCS9Attributes unauthenticatedAttributes; public SignerInfo(X500Name issuerName, BigInt serial, AlgorithmId digestAlgorithmId, AlgorithmId digestEncryptionAlgorithmId, byte[] encryptedDigest) { this.version = new BigInt(1); this.issuerName = issuerName; this.certificateSerialNumber = serial; this.digestAlgorithmId = digestAlgorithmId; this.digestEncryptionAlgorithmId = digestEncryptionAlgorithmId; this.encryptedDigest = encryptedDigest; } public SignerInfo(X500Name issuerName, BigInt serial, AlgorithmId digestAlgorithmId, PKCS9Attributes authenticatedAttributes, AlgorithmId digestEncryptionAlgorithmId, byte[] encryptedDigest, PKCS9Attributes unauthenticatedAttributes) { this.version = new BigInt(1); this.issuerName = issuerName; this.certificateSerialNumber = serial; this.digestAlgorithmId = digestAlgorithmId; this.authenticatedAttributes = authenticatedAttributes; this.digestEncryptionAlgorithmId = digestEncryptionAlgorithmId; this.encryptedDigest = encryptedDigest; this.unauthenticatedAttributes = unauthenticatedAttributes; } public SignerInfo(DerInputStream derin) throws IOException, ParsingException { // version version = derin.getInteger(); // issuerAndSerialNumber DerValue[] issuerAndSerialNumber = derin.getSequence(2); byte[] issuerBytes = issuerAndSerialNumber[0].toByteArray(); issuerName = new X500Name(new DerValue(DerValue.tag_Sequence, issuerBytes)); certificateSerialNumber = issuerAndSerialNumber[1].getInteger(); // digestAlgorithmId DerValue tmp = derin.getDerValue(); digestAlgorithmId = AlgorithmId.parse(tmp); /* * check if set of auth attributes (implicit tag) is provided * (auth attributes are OPTIONAL) */ if ((byte) (derin.peekByte()) == (byte) 0xA0) { authenticatedAttributes = new PKCS9Attributes(derin); } // digestEncryptionAlgorithmId - little RSA naming scheme - // signature == encryption... tmp = derin.getDerValue(); digestEncryptionAlgorithmId = AlgorithmId.parse(tmp); // encryptedDigest encryptedDigest = derin.getOctetString(); /* * check if set of unauth attributes (implicit tag) is provided * (unauth attributes are OPTIONAL) */ if (derin.available() != 0 && (byte) (derin.peekByte()) == (byte) 0xA1) { unauthenticatedAttributes = new PKCS9Attributes(derin); } // all done if (derin.available() != 0) { throw new ParsingException("extra data at the end"); } } public void encode(DerOutputStream out) throws IOException { derEncode(out); } /** * DER encode this object onto an output stream. * Implements the DerEncoder interface. * * @param out * the output stream on which to write the DER encoding. * * @exception IOException on encoding error. */ @Override public void derEncode(OutputStream out) throws IOException { try (DerOutputStream tmp = new DerOutputStream()) { DerOutputStream seq = new DerOutputStream(); seq.putInteger(version); DerOutputStream issuerAndSerialNumber = new DerOutputStream(); issuerName.encode(issuerAndSerialNumber); issuerAndSerialNumber.putInteger(certificateSerialNumber); seq.write(DerValue.tag_Sequence, issuerAndSerialNumber); digestAlgorithmId.encode(seq); // encode authenticated attributes if there are any if (authenticatedAttributes != null) authenticatedAttributes.encode((byte) 0xA0, seq); digestEncryptionAlgorithmId.encode(seq); seq.putOctetString(encryptedDigest); // encode unauthenticated attributes if there are any if (unauthenticatedAttributes != null) unauthenticatedAttributes.encode((byte) 0xA1, seq); tmp.write(DerValue.tag_Sequence, seq); out.write(tmp.toByteArray()); } } public X509Certificate getCertificate(PKCS7 block) throws IOException { return block.getCertificate(certificateSerialNumber, issuerName); } /* Returns null if verify fails, this signerInfo if verify succeeds. */ SignerInfo verify(PKCS7 block, byte[] data) throws NoSuchAlgorithmException, SignatureException { try { ContentInfo content = block.getContentInfo(); if (data == null) { data = content.getContentBytes(); } String digestAlgname = getDigestAlgorithmId().getName(); byte[] dataSigned; // if there are authenticate attributes, get the message // digest and compare it with the digest of data if (authenticatedAttributes == null) { dataSigned = data; } else { // first, check content type ObjectIdentifier contentType = (ObjectIdentifier) authenticatedAttributes.getAttributeValue( PKCS9Attribute.CONTENT_TYPE_OID); if (contentType == null || !contentType.equals(content.contentType)) return null; // contentType does not match, bad SignerInfo // now, check message digest byte[] messageDigest = (byte[]) authenticatedAttributes.getAttributeValue( PKCS9Attribute.MESSAGE_DIGEST_OID); if (messageDigest == null) // fail if there is no message digest return null; MessageDigest md = MessageDigest.getInstance(digestAlgname); byte[] computedMessageDigest = md.digest(data); if (messageDigest.length != computedMessageDigest.length) return null; for (int i = 0; i < messageDigest.length; i++) { if (messageDigest[i] != computedMessageDigest[i]) return null; } // message digest attribute matched // digest of original data // the data actually signed is the DER encoding of // the authenticated attributes (tagged with // the "SET OF" tag, not 0xA0). dataSigned = authenticatedAttributes.getDerEncoding(); } // put together digest algorithm and encryption algorithm // to form signing algorithm String encryptionAlgname = getDigestEncryptionAlgorithmId().getName(); String algname; if (encryptionAlgname.equals("DSA") || encryptionAlgname.equals("SHA1withDSA")) { algname = "DSA"; } else { algname = digestAlgname + "/" + encryptionAlgname; } Signature sig = Signature.getInstance(algname); X509Certificate cert = getCertificate(block); if (cert == null) { return null; } PublicKey key = cert.getPublicKey(); sig.initVerify(key); sig.update(dataSigned); if (sig.verify(encryptedDigest)) { return this; } } catch (IOException e) { throw new SignatureException("IO error verifying signature:\n" + e.getMessage()); } catch (InvalidKeyException e) { throw new SignatureException("InvalidKey: " + e.getMessage()); } return null; } /* Verify the content of the pkcs7 block. */ SignerInfo verify(PKCS7 block) throws NoSuchAlgorithmException, SignatureException { return verify(block, null); } public BigInt getVersion() { return version; } public X500Name getIssuerName() { return issuerName; } public BigInt getCertificateSerialNumber() { return certificateSerialNumber; } public AlgorithmId getDigestAlgorithmId() { return digestAlgorithmId; } public PKCS9Attributes getAuthenticatedAttributes() { return authenticatedAttributes; } public AlgorithmId getDigestEncryptionAlgorithmId() { return digestEncryptionAlgorithmId; } public byte[] getEncryptedDigest() { return encryptedDigest; } public PKCS9Attributes getUnauthenticatedAttributes() { return unauthenticatedAttributes; } @Override public String toString() { org.mozilla.jss.netscape.security.util.PrettyPrintFormat pp = new org.mozilla.jss.netscape.security.util.PrettyPrintFormat(" ", 20); String digestbits = pp.toHexString(encryptedDigest); String out = ""; out += "Signer Info for (issuer): " + issuerName + "\n"; out += "\tversion: " + version + "\n"; out += "\tcertificateSerialNumber: " + certificateSerialNumber + "\n"; out += "\tdigestAlgorithmId: " + digestAlgorithmId + "\n"; if (authenticatedAttributes != null) { out += "\tauthenticatedAttributes: " + authenticatedAttributes + "\n"; } out += "\tdigestEncryptionAlgorithmId: " + digestEncryptionAlgorithmId + "\n"; out += "\tencryptedDigest: " + "\n" + digestbits + "\n"; if (unauthenticatedAttributes != null) { out += "\tunauthenticatedAttributes: " + unauthenticatedAttributes + "\n"; } return out; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/provider/000077500000000000000000000000001412550063600253115ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/provider/CMS.java000066400000000000000000000032471412550063600266040ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.provider; import java.security.AccessController; import java.security.Provider; /** * The CMS Security Provider. */ public final class CMS extends Provider { /** * */ private static final long serialVersionUID = 1065207998900104219L; private static final String INFO = "CMS [X.509 certificates]"; public CMS() { /* We are the CMS provider */ super("CMS", 1.0, INFO); AccessController.doPrivileged(new java.security.PrivilegedAction() { @Override public Object run() { /* * Certificates */ put("CertificateFactory.X.509", "org.mozilla.jss.netscape.security.provider.X509CertificateFactory"); put("Alg.Alias.CertificateFactory.X.509", "X.509"); return null; } }); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/provider/DSAKeyFactory.java000066400000000000000000000221031412550063600305620ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.provider; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyFactorySpi; import java.security.PrivateKey; import java.security.PublicKey; import java.security.interfaces.DSAParams; import java.security.spec.DSAPrivateKeySpec; import java.security.spec.DSAPublicKeySpec; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; /** * This class implements the DSA key factory of the Sun provider. * * @author Jan Luehe * * @version 1.8, 97/12/10 * * @since JDK1.2 */ public class DSAKeyFactory extends KeyFactorySpi { /** * Generates a public key object from the provided key specification * (key material). * * @param keySpec the specification (key material) of the public key * * @return the public key * * @exception InvalidKeySpecException if the given key specification * is inappropriate for this key factory to produce a public key. */ @Override protected PublicKey engineGeneratePublic(KeySpec keySpec) throws InvalidKeySpecException { try { if (keySpec instanceof DSAPublicKeySpec) { DSAPublicKeySpec dsaPubKeySpec = (DSAPublicKeySpec) keySpec; return new DSAPublicKey(dsaPubKeySpec.getY(), dsaPubKeySpec.getP(), dsaPubKeySpec.getQ(), dsaPubKeySpec.getG()); } else if (keySpec instanceof X509EncodedKeySpec) { return new DSAPublicKey(((X509EncodedKeySpec) keySpec).getEncoded()); } else { throw new InvalidKeySpecException("Inappropriate key specification"); } } catch (InvalidKeyException e) { throw new InvalidKeySpecException("Inappropriate key specification: " + e.getMessage()); } } /** * Generates a private key object from the provided key specification * (key material). * * @param keySpec the specification (key material) of the private key * * @return the private key * * @exception InvalidKeySpecException if the given key specification * is inappropriate for this key factory to produce a private key. */ @Override protected PrivateKey engineGeneratePrivate(KeySpec keySpec) throws InvalidKeySpecException { try { if (keySpec instanceof DSAPrivateKeySpec) { DSAPrivateKeySpec dsaPrivKeySpec = (DSAPrivateKeySpec) keySpec; return new DSAPrivateKey(dsaPrivKeySpec.getX(), dsaPrivKeySpec.getP(), dsaPrivKeySpec.getQ(), dsaPrivKeySpec.getG()); } else if (keySpec instanceof PKCS8EncodedKeySpec) { return new DSAPrivateKey(((PKCS8EncodedKeySpec) keySpec).getEncoded()); } else { throw new InvalidKeySpecException("Inappropriate key specification"); } } catch (InvalidKeyException e) { throw new InvalidKeySpecException("Inappropriate key specification: " + e.getMessage()); } } /** * Returns a specification (key material) of the given key object * in the requested format. * * @param key the key * * @param keySpec the requested format in which the key material shall be * returned * * @return the underlying key specification (key material) in the * requested format * * @exception InvalidKeySpecException if the requested key specification is * inappropriate for the given key, or the given key cannot be processed * (e.g., the given key has an unrecognized algorithm or format). */ @Override @SuppressWarnings("unchecked") protected T engineGetKeySpec(Key key, Class keySpec) throws InvalidKeySpecException { DSAParams params; try { if (key instanceof java.security.interfaces.DSAPublicKey) { // Determine valid key specs Class dsaPubKeySpec = Class.forName ("java.security.spec.DSAPublicKeySpec"); Class x509KeySpec = Class.forName ("java.security.spec.X509EncodedKeySpec"); if (dsaPubKeySpec.isAssignableFrom(keySpec)) { java.security.interfaces.DSAPublicKey dsaPubKey = (java.security.interfaces.DSAPublicKey) key; params = dsaPubKey.getParams(); return (T) new DSAPublicKeySpec(dsaPubKey.getY(), params.getP(), params.getQ(), params.getG()); } else if (x509KeySpec.isAssignableFrom(keySpec)) { return (T) new X509EncodedKeySpec(key.getEncoded()); } else { throw new InvalidKeySpecException("Inappropriate key specification"); } } else if (key instanceof java.security.interfaces.DSAPrivateKey) { // Determine valid key specs Class dsaPrivKeySpec = Class.forName ("java.security.spec.DSAPrivateKeySpec"); Class pkcs8KeySpec = Class.forName ("java.security.spec.PKCS8EncodedKeySpec"); if (dsaPrivKeySpec.isAssignableFrom(keySpec)) { java.security.interfaces.DSAPrivateKey dsaPrivKey = (java.security.interfaces.DSAPrivateKey) key; params = dsaPrivKey.getParams(); return (T) new DSAPrivateKeySpec(dsaPrivKey.getX(), params.getP(), params.getQ(), params.getG()); } else if (pkcs8KeySpec.isAssignableFrom(keySpec)) { return (T) new PKCS8EncodedKeySpec(key.getEncoded()); } else { throw new InvalidKeySpecException("Inappropriate key specification"); } } else { throw new InvalidKeySpecException("Inappropriate key type"); } } catch (ClassNotFoundException e) { throw new InvalidKeySpecException("Unsupported key specification: " + e.getMessage()); } } /** * Translates a key object, whose provider may be unknown or potentially * untrusted, into a corresponding key object of this key factory. * * @param key the key whose provider is unknown or untrusted * * @return the translated key * * @exception InvalidKeyException if the given key cannot be processed by * this key factory. */ @Override protected Key engineTranslateKey(Key key) throws InvalidKeyException { try { if (key instanceof java.security.interfaces.DSAPublicKey) { // Check if key originates from this factory if (key instanceof org.mozilla.jss.netscape.security.provider.DSAPublicKey) { return key; } // Convert key to spec DSAPublicKeySpec dsaPubKeySpec = engineGetKeySpec(key, DSAPublicKeySpec.class); // Create key from spec, and return it return engineGeneratePublic(dsaPubKeySpec); } else if (key instanceof java.security.interfaces.DSAPrivateKey) { // Check if key originates from this factory if (key instanceof org.mozilla.jss.netscape.security.provider.DSAPrivateKey) { return key; } // Convert key to spec DSAPrivateKeySpec dsaPrivKeySpec = engineGetKeySpec(key, DSAPrivateKeySpec.class); // Create key from spec, and return it return engineGeneratePrivate(dsaPrivKeySpec); } else { throw new InvalidKeyException("Wrong algorithm type"); } } catch (InvalidKeySpecException e) { throw new InvalidKeyException("Cannot translate key: " + e.getMessage()); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/provider/DSAParameters.java000066400000000000000000000111761412550063600306150ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.provider; import java.io.IOException; import java.math.BigInteger; import java.security.AlgorithmParametersSpi; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.DSAParameterSpec; import java.security.spec.InvalidParameterSpecException; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class implements the parameter set used by the * Digital Signature Algorithm as specified in the FIPS 186 * standard. * * @author Jan Luehe * * @version 1.8, 97/12/10 * * @since JDK1.2 */ public class DSAParameters extends AlgorithmParametersSpi { // the prime (p) protected BigInteger p; // the sub-prime (q) protected BigInteger q; // the base (g) protected BigInteger g; @Override protected void engineInit(AlgorithmParameterSpec paramSpec) throws InvalidParameterSpecException { if (!(paramSpec instanceof DSAParameterSpec)) { throw new InvalidParameterSpecException("Inappropriate parameter specification"); } this.p = ((DSAParameterSpec) paramSpec).getP(); this.q = ((DSAParameterSpec) paramSpec).getQ(); this.g = ((DSAParameterSpec) paramSpec).getG(); } @Override protected void engineInit(byte[] params) throws IOException { DerValue encodedParams = new DerValue(params); if (encodedParams.tag != DerValue.tag_Sequence) { throw new IOException("DSA params parsing error"); } encodedParams.data.reset(); this.p = encodedParams.data.getInteger().toBigInteger(); this.q = encodedParams.data.getInteger().toBigInteger(); this.g = encodedParams.data.getInteger().toBigInteger(); if (encodedParams.data.available() != 0) { throw new IOException("encoded params have " + encodedParams.data.available() + " extra bytes"); } } @Override protected void engineInit(byte[] params, String decodingMethod) throws IOException { engineInit(params); } @Override @SuppressWarnings("unchecked") protected T engineGetParameterSpec(Class paramSpec) throws InvalidParameterSpecException { try { Class dsaParamSpec = Class.forName ("java.security.spec.DSAParameterSpec"); if (dsaParamSpec.isAssignableFrom(paramSpec)) { return (T) new DSAParameterSpec(this.p, this.q, this.g); } else { throw new InvalidParameterSpecException("Inappropriate parameter Specification"); } } catch (ClassNotFoundException e) { throw new InvalidParameterSpecException("Unsupported parameter specification: " + e.getMessage()); } } @Override protected byte[] engineGetEncoded() throws IOException { try (DerOutputStream out = new DerOutputStream()) { DerOutputStream bytes = new DerOutputStream(); bytes.putInteger(new BigInt(p.toByteArray())); bytes.putInteger(new BigInt(q.toByteArray())); bytes.putInteger(new BigInt(g.toByteArray())); out.write(DerValue.tag_Sequence, bytes); return out.toByteArray(); } } @Override protected byte[] engineGetEncoded(String encodingMethod) throws IOException { return engineGetEncoded(); } /* * Returns a formatted string describing the parameters. */ @Override protected String engineToString() { return "\n\tp: " + new BigInt(p).toString() + "\n\tq: " + new BigInt(q).toString() + "\n\tg: " + new BigInt(g).toString() + "\n"; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/provider/DSAPrivateKey.java000066400000000000000000000117011412550063600305670ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.provider; import java.io.IOException; import java.math.BigInteger; import java.security.AlgorithmParameters; import java.security.InvalidKeyException; import java.security.interfaces.DSAParams; import java.security.spec.DSAParameterSpec; import java.security.spec.InvalidParameterSpecException; import org.mozilla.jss.netscape.security.pkcs.PKCS8Key; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.x509.AlgIdDSA; /** * A PKCS#8 private key for the Digital Signature Algorithm. * * @author Benjamin Renaud * * @version 1.47, 97/12/10 * * @see DSAPublicKey * @see AlgIdDSA */ public final class DSAPrivateKey extends PKCS8Key implements java.security.interfaces.DSAPrivateKey { /** use serialVersionUID from JDK 1.1. for interoperability */ private static final long serialVersionUID = -3244453684193605938L; /* the private key */ private BigInteger x; /* * Keep this constructor for backwards compatibility with JDK1.1. */ public DSAPrivateKey() { } /** * Make a DSA private key out of a private key and three parameters. */ public DSAPrivateKey(BigInteger x, BigInteger p, BigInteger q, BigInteger g) throws InvalidKeyException { this.x = x; algid = new AlgIdDSA(p, q, g); try { key = new DerValue(DerValue.tag_Integer, x.toByteArray()).toByteArray(); encode(); } catch (IOException e) { throw new InvalidKeyException("could not DER encode x: " + e.getMessage()); } } /** * Make a DSA private key from its DER encoding (PKCS #8). */ public DSAPrivateKey(byte[] encoded) throws InvalidKeyException { clearOldKey(); decode(encoded); } /** * Returns the DSA parameters associated with this key, or null if the * parameters could not be parsed. */ @Override public DSAParams getParams() { try { if (algid instanceof DSAParams) { return (DSAParams) algid; } else { AlgorithmParameters algParams = algid.getParameters(); if (algParams == null) { return null; } return algParams.getParameterSpec(DSAParameterSpec.class); } } catch (InvalidParameterSpecException e) { return null; } } /** * Get the raw private key, x, without the parameters. * */ @Override public BigInteger getX() { return x; } private void clearOldKey() { int i; if (this.encodedKey != null) { for (i = 0; i < this.encodedKey.length; i++) { this.encodedKey[i] = (byte) 0x00; } } if (this.key != null) { for (i = 0; i < this.key.length; i++) { this.key[i] = (byte) 0x00; } } } @Override public String toString() { return "Sun DSA Private Key \nparameters:" + algid + "\nx: " + x.toString(16) + "\n"; } @Override protected void parseKeyBits() throws InvalidKeyException { DerInputStream in = new DerInputStream(key); try { x = in.getInteger().toBigInteger(); } catch (IOException e) { throw new InvalidKeyException(e.getMessage()); } } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((x == null) ? 0 : x.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; DSAPrivateKey other = (DSAPrivateKey) obj; if (x == null) { if (other.x != null) return false; } else if (!x.equals(other.x)) return false; return true; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/provider/DSAPublicKey.java000066400000000000000000000114101412550063600303700ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.provider; import java.io.IOException; import java.math.BigInteger; import java.security.AlgorithmParameters; import java.security.InvalidKeyException; import java.security.interfaces.DSAParams; import java.security.spec.DSAParameterSpec; import java.security.spec.InvalidParameterSpecException; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.x509.AlgIdDSA; import org.mozilla.jss.netscape.security.x509.X509Key; /** * An X.509 public key for the Digital Signature Algorithm. * * @author Benjamin Renaud * * @version 1.52, 97/12/10 * * @see DSAPrivateKey * @see AlgIdDSA */ public final class DSAPublicKey extends X509Key implements java.security.interfaces.DSAPublicKey { /** use serialVersionUID from JDK 1.1. for interoperability */ private static final long serialVersionUID = -2994193307391104133L; /* the public key */ private BigInteger y; /* * Keep this constructor for backwards compatibility with JDK1.1. */ public DSAPublicKey() { } /** * Make a DSA public key out of a public key and three parameters. */ public DSAPublicKey(BigInteger y, BigInteger p, BigInteger q, BigInteger g) throws InvalidKeyException { this.y = y; algid = new AlgIdDSA(p, q, g); try { key = new DerValue(DerValue.tag_Integer, y.toByteArray()).toByteArray(); encode(); } catch (IOException e) { throw new InvalidKeyException("could not DER encode y: " + e.getMessage()); } } /** * Make a DSA public key from its DER encoding (X.509). */ public DSAPublicKey(byte[] encoded) throws InvalidKeyException { decode(encoded); } /** * Returns the DSA parameters associated with this key, or null if the * parameters could not be parsed. */ @Override public DSAParams getParams() { try { if (algid instanceof DSAParams) { return (DSAParams) algid; } else { DSAParameterSpec paramSpec; AlgorithmParameters algParams = algid.getParameters(); if (algParams == null) { return null; } paramSpec = algParams.getParameterSpec (DSAParameterSpec.class); return paramSpec; } } catch (InvalidParameterSpecException e) { return null; } } /** * Get the raw public value, y, without the parameters. * */ @Override public BigInteger getY() { return y; } @Override public String toString() { return "Sun DSA Public Key\n Parameters:" + algid + "\n y:\n" + (new BigInt(y)).toString() + "\n"; } @Override protected void parseKeyBits() throws InvalidKeyException { try { DerInputStream in = new DerInputStream(key); y = in.getInteger().toBigInteger(); } catch (IOException e) { throw new InvalidKeyException("Invalid key: y value\n" + e.getMessage()); } } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((y == null) ? 0 : y.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; DSAPublicKey other = (DSAPublicKey) obj; if (y == null) { if (other.y != null) return false; } else if (!y.equals(other.y)) return false; return true; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/provider/RSAPublicKey.java000066400000000000000000000135611412550063600304170ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.provider; import java.io.IOException; import java.security.InvalidKeyException; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; import org.mozilla.jss.netscape.security.x509.AlgorithmId; import org.mozilla.jss.netscape.security.x509.X509Key; /** * An X.509 public key for the RSA Algorithm. * * @author galperin * * @version $Revision$, $Date$ * */ public final class RSAPublicKey extends X509Key { /* XXX This currently understands only PKCS#1 RSA Encryption OID and parameter format Later we may consider adding X509v3 OID for RSA keys. Besides different OID it also has a parameter equal to modulus size in bits (redundant!) */ /** * */ private static final long serialVersionUID = 7764823589128565374L; private static final ObjectIdentifier ALGORITHM_OID = AlgorithmId.RSAEncryption_oid; private BigInt modulus; private BigInt publicExponent; /* * Keep this constructor for backwards compatibility with JDK1.1. */ public RSAPublicKey() { } /** * Make a RSA public key out of a public exponent and modulus */ public RSAPublicKey(BigInt modulus, BigInt publicExponent) throws InvalidKeyException { this.modulus = modulus; this.publicExponent = publicExponent; this.algid = new AlgorithmId(ALGORITHM_OID); try (DerOutputStream out = new DerOutputStream()) { out.putInteger(modulus); out.putInteger(publicExponent); key = (new DerValue(DerValue.tag_Sequence, out.toByteArray())).toByteArray(); encode(); } catch (IOException ex) { throw new InvalidKeyException("could not DER encode : " + ex.getMessage()); } } /** * Make a RSA public key from its DER encoding (X.509). */ public RSAPublicKey(byte[] encoded) throws InvalidKeyException { decode(encoded); } /** * Get key size as number of bits in modulus * (Always rounded up to a multiple of 8) * */ public int getKeySize() { return this.modulus.byteLength() * 8; } /** * Get the raw public exponent * */ public BigInt getPublicExponent() { return this.publicExponent; } /** * Get the raw modulus * */ public BigInt getModulus() { return this.modulus; } @Override public String toString() { return "RSA Public Key\n Algorithm: " + algid + "\n modulus:\n" + this.modulus.toString() + "\n" + "\n publicExponent:\n" + this.publicExponent.toString() + "\n"; } @Override protected void parseKeyBits() throws InvalidKeyException { if (!this.algid.getOID().equals(ALGORITHM_OID) && !this.algid.getOID().equals(AlgorithmId.RSA_oid)) { throw new InvalidKeyException("Key algorithm OID is not RSA"); } try { DerValue val = new DerValue(key); if (val.tag != DerValue.tag_Sequence) { throw new InvalidKeyException("Invalid RSA public key format:" + " must be a SEQUENCE"); } DerInputStream in = val.data; this.modulus = in.getInteger(); this.publicExponent = in.getInteger(); } catch (IOException e) { throw new InvalidKeyException("Invalid RSA public key: " + e.getMessage()); } } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((modulus == null) ? 0 : modulus.hashCode()); result = prime * result + ((publicExponent == null) ? 0 : publicExponent.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; RSAPublicKey other = (RSAPublicKey) obj; if (modulus == null) { if (other.modulus != null) return false; } else if (!modulus.equals(other.modulus)) return false; if (publicExponent == null) { if (other.publicExponent != null) return false; } else if (!publicExponent.equals(other.publicExponent)) return false; return true; } public boolean bigIntEquals(BigInt x, BigInt y) { if (x == null) { if (y != null) { return false; } } else { if (!x.equals(y)) { return false; } } return true; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/provider/Sun.java000066400000000000000000000060111412550063600267170ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.provider; import java.security.Provider; /** * The SUN Security Provider. * * @author Benjamin Renaud * * @version 1.24, 97/12/10 */ /** * Defines the SUN provider. * * Algorithm supported, and their names: * * - SHA-1 is the message digest scheme decribed FIPS 180-1. * Aliases for SHA-1 are SHA. * * - DSA is the signature scheme described in FIPS 186. (SHA used in * DSA is SHA-1: FIPS 186 with Change No 1.) Aliases for DSA are * SHA/DSA, SHA-1/DSA, SHA1/DSA, DSS and the object identifier * strings "OID.1.3.14.3.2.13", "OID.1.3.14.3.2.27" and * "OID.1.2.840.10040.4.3". * * - DSA is the key generation scheme as described in FIPS 186. * Aliases for DSA include the OID strings "OID.1.3.14.3.2.12" * and "OID.1.2.840.10040.4.1". * * - MD5 is the message digest scheme described in RFC 1321. * There are no aliases for MD5. * * Notes: The name of algorithm described in FIPS-180 is SHA-0, and is * not supported by the SUN provider.) */ public final class Sun extends Provider { /** * */ private static final long serialVersionUID = 9134942296334703727L; private static String info = "SUN Security Provider v1.0, " + "DSA signing and key generation, SHA-1 and MD5 message digests."; public Sun() { /* We are the SUN provider */ super("SUN", 1.0, info); try { // AccessController.beginPrivileged(); // the following are not according to our formal spec but // are still supported put("Alg.Alias.KeyPairGenerator.1.3.14.3.2.12", "DSA"); put("Alg.Alias.KeyPairGenerator.1.2.840.10040.4.1", "DSA"); /* * Algorithm Parameter engines */ put("AlgorithmParameters.DSA", "org.mozilla.jss.netscape.security.provider.DSAParameters"); put("Alg.Alias.AlgorithmParameters.1.3.14.3.2.12", "DSA"); put("Alg.Alias.AlgorithmParameters.1.2.840.10040.4.1", "DSA"); /* * Key factories */ put("KeyFactory.DSA", "org.mozilla.jss.netscape.security.provider.DSAKeyFactory"); } finally { // AccessController.endPrivileged(); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/provider/X509CertificateFactory.java000066400000000000000000000041401412550063600323130ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.provider; import java.io.InputStream; import java.security.cert.CRL; import java.security.cert.CRLException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactorySpi; import java.util.Collection; import org.mozilla.jss.netscape.security.x509.X509CRLImpl; import org.mozilla.jss.netscape.security.x509.X509CertImpl; import org.mozilla.jss.netscape.security.x509.X509ExtensionException; public class X509CertificateFactory extends CertificateFactorySpi { @Override public Certificate engineGenerateCertificate(InputStream inStream) throws CertificateException { return new X509CertImpl(inStream); } @Override public Collection engineGenerateCertificates(InputStream inStream) throws CertificateException { return null; } @Override public CRL engineGenerateCRL(InputStream inStream) throws CRLException { X509CRLImpl crl = null; try { crl = new X509CRLImpl(inStream); } catch (X509ExtensionException e) { ; } return crl; } @Override public Collection engineGenerateCRLs(InputStream inStream) throws CRLException { return null; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/000077500000000000000000000000001412550063600244345ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/ASN1CharStrConvMap.java000066400000000000000000000123211412550063600305530ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; import java.util.HashMap; import java.util.Iterator; import java.util.Map; /** * Maps a ASN.1 character string type to a charset encoder and decoder. * The converter is used to convert a DerValue of a ASN.1 character string type * from bytes to unicode characters and vice versa. * *

* A global default ASN1CharStrConvMap is created when the class is initialized. The global default map is extensible. * * @author Lily Hsiao * @author Slava Galperin * */ public class ASN1CharStrConvMap { // public constructors /** * Constructs a ASN1CharStrConvMap. */ public ASN1CharStrConvMap() { } /** * Get an encoder for the specified DER tag. * * @param tag A DER tag of a ASN.1 character string type, * for example DerValue.tag_PrintableString. * * @return An encoder for the DER tag. */ public CharsetEncoder getEncoder(byte tag) { Charset charset = charsets.get(tag); if (charset == null) return null; return charset.newEncoder(); } /** * Get a decoder for the given DER tag. * * @param tag A DER tag of a ASN.1 character string type, * for example DerValue.tag_PrintableString. * * @return A decoder for the DER tag. */ public CharsetDecoder getDecoder(byte tag) { Charset charset = charsets.get(tag); if (charset == null) return null; return charset.newDecoder(); } /** * Add a tag-charset entry in the map. * * @param tag A DER tag of a ASN.1 character string type, * ex. DerValue.tag_IA5String * @param charset A charset for the tag. */ public void addEntry(byte tag, Charset charset) { Charset currentCharset = charsets.get(tag); if (currentCharset != null) { if (currentCharset != charset) { throw new IllegalArgumentException( "a DER tag to converter entry already exists."); } else { return; } } charsets.put(tag, charset); } /** * Get an iterator of all tags in the map. * * @return An Iterator of DER tags in the map as Bytes. */ public Iterator getTags() { return charsets.keySet().iterator(); } // static public methods. /** * Get the global ASN1CharStrConvMap. * * @return The global default ASN1CharStrConvMap. */ static public ASN1CharStrConvMap getDefault() { return defaultMap; } /** * Set the global default ASN1CharStrConvMap. * * @param newDefault The new default ASN1CharStrConvMap. */ static public void setDefault(ASN1CharStrConvMap newDefault) { if (newDefault == null) throw new IllegalArgumentException( "Cannot set a null default Der Tag Converter map"); defaultMap = newDefault; } // private methods and variables. private Map charsets = new HashMap(); private static ASN1CharStrConvMap defaultMap; /** * Create the default converter map on initialization */ static { ASN1CharsetProvider provider = new ASN1CharsetProvider(); defaultMap = new ASN1CharStrConvMap(); defaultMap.addEntry(DerValue.tag_PrintableString, provider.charsetForName("ASN.1-Printable")); defaultMap.addEntry(DerValue.tag_VisibleString, provider.charsetForName("ASN.1-Printable")); defaultMap.addEntry(DerValue.tag_IA5String, provider.charsetForName("ASN.1-IA5")); defaultMap.addEntry(DerValue.tag_BMPString, Charset.forName("UnicodeBig")); defaultMap.addEntry(DerValue.tag_UniversalString, provider.charsetForName("ASN.1-Universal")); // XXX this is an oversimplified implementation of T.61 strings, it // doesn't handle all cases defaultMap.addEntry(DerValue.tag_T61String, Charset.forName("ISO-8859-1")); // UTF8String added to ASN.1 in 1998 defaultMap.addEntry(DerValue.tag_UTF8String, Charset.forName("UTF-8")); defaultMap.addEntry(DerValue.tag_GeneralString, Charset.forName("UTF-8")); }; }; jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/ASN1CharsetProvider.java000066400000000000000000000014671412550063600310360ustar00rootroot00000000000000package org.mozilla.jss.netscape.security.util; import java.nio.charset.Charset; import java.nio.charset.spi.CharsetProvider; import java.util.HashMap; import java.util.Iterator; import java.util.Map; public class ASN1CharsetProvider extends CharsetProvider { protected Map charsets = new HashMap(); public ASN1CharsetProvider() { addCharset(new PrintableCharset()); addCharset(new IA5Charset()); addCharset(new UniversalCharset()); } @Override public Iterator charsets() { return charsets.values().iterator(); } @Override public Charset charsetForName(String charsetName) { return charsets.get(charsetName); } public void addCharset(Charset cs) { charsets.put(cs.name(), cs); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/BigInt.java000066400000000000000000000153761412550063600264670ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.io.Serializable; import java.math.BigInteger; import java.util.Arrays; /** * A low-overhead arbitrary-precision unsigned integer. * This is intended for use with ASN.1 parsing, and printing of * such parsed values. Convert to "BigInteger" if you need to do * arbitrary precision arithmetic, rather than just represent * the number as a wrapped array of bytes. * *

* NOTE: This class may eventually disappear, to * be supplanted by big-endian byte arrays which hold both signed * and unsigned arbitrary-precision integers. * * @version 1.23 * @author David Brownell */ public final class BigInt implements Serializable { private static final long serialVersionUID = 705094142021888265L; // Big endian -- MSB first. private byte[] places; /** * Constructs a "Big" integer from a set of (big-endian) bytes. * Leading zeroes should be stripped off. * * @param data a sequence of bytes, most significant bytes/digits * first. CONSUMED. */ public BigInt(byte[] data) { places = data.clone(); } /** * Constructs a "Big" integer from a "BigInteger", which must be * positive (or zero) in value. */ public BigInt(BigInteger i) { byte[] temp = i.toByteArray(); if ((temp[0] & 0x80) != 0) throw new IllegalArgumentException("negative BigInteger"); // XXX we assume exactly _one_ sign byte is used... if (temp[0] != 0) places = temp; else { // Note that if i = new BigInteger("0"), // i.toByteArray() contains only 1 zero. if (temp.length == 1) { places = new byte[1]; places[0] = (byte) 0; } else { places = new byte[temp.length - 1]; for (int j = 1; j < temp.length; j++) places[j - 1] = temp[j]; } } } /** * Constructs a "Big" integer from a normal Java integer. * * @param i the java primitive integer */ public BigInt(int i) { if (i < (1 << 8)) { places = new byte[1]; places[0] = (byte) i; } else if (i < (1 << 16)) { places = new byte[2]; places[0] = (byte) (i >> 8); places[1] = (byte) i; } else if (i < (1 << 24)) { places = new byte[3]; places[0] = (byte) (i >> 16); places[1] = (byte) (i >> 8); places[2] = (byte) i; } else { places = new byte[4]; places[0] = (byte) (i >> 24); places[1] = (byte) (i >> 16); places[2] = (byte) (i >> 8); places[3] = (byte) i; } } /** * Converts the "big" integer to a java primitive integer. * * @exception NumberFormatException if 32 bits is insufficient. */ public int toInt() { if (places.length > 4) throw new NumberFormatException("BigInt.toInt, too big"); int retval = 0, i = 0; for (; i < places.length; i++) retval = (retval << 8) + (places[i] & 0xff); return retval; } /** * Returns a hexadecimal printed representation. The value is * formatted to fit on lines of at least 75 characters, with * embedded newlines. Words are separated for readability, * with eight words (32 bytes) per line. */ @Override public String toString() { return hexify(); } /** * Returns a BigInteger value which supports many arithmetic * operations. Assumes negative values will never occur. */ public BigInteger toBigInteger() { return new BigInteger(1, places); } /** * Returns the length of the data as a byte array. */ public int byteLength() { return places.length; } /** * Returns the data as a byte array. The most significant bit * of the array is bit zero (as in java.math.BigInteger). */ public byte[] toByteArray() { if (places.length == 0) { byte zero[] = new byte[1]; zero[0] = (byte) 0; return zero; } else { return places.clone(); } } private static final String digits = "0123456789abcdef"; private String hexify() { if (places.length == 0) return " 0 "; StringBuffer buf = new StringBuffer(places.length * 2); buf.append(" "); // four spaces for (int i = 0; i < places.length; i++) { buf.append(digits.charAt((places[i] >> 4) & 0x0f)); buf.append(digits.charAt(places[i] & 0x0f)); if (((i + 1) % 32) == 0) { if ((i + 1) != places.length) buf.append("\n "); // line after four words } else if (((i + 1) % 4) == 0) buf.append(' '); // space between words } return buf.toString(); } /** * Returns true iff the parameter is a numerically equivalent * BigInt. * * @param other the object being compared with this one. */ @Override public boolean equals(Object other) { if (other instanceof BigInt) return equals((BigInt) other); return false; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + Arrays.hashCode(places); return result; } /** * Returns true iff the parameter is numerically equivalent. * * @param other the BigInt being compared with this one. */ public boolean equals(BigInt other) { if (this == other) return true; byte[] otherPlaces = other.toByteArray(); if (places.length != otherPlaces.length) return false; for (int i = 0; i < places.length; i++) if (places[i] != otherPlaces[i]) return false; return true; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/BitArray.java000066400000000000000000000174661412550063600270320ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.io.ByteArrayOutputStream; /** * A packed array of booleans. * * @author Joshua Bloch * @author Douglas Hoover * @version 1.2 97/12/10 */ public class BitArray { private byte[] repn; private int length; private static final int BITS_PER_UNIT = 8; private static int subscript(int idx) { return idx / BITS_PER_UNIT; } private static int position(int idx) { // bits big-endian in each unit return 1 << (BITS_PER_UNIT - 1 - (idx % BITS_PER_UNIT)); } /** * Creates a BitArray of the specified size, initialized to zeros. */ public BitArray(int length) throws IllegalArgumentException { if (length < 0) { throw new IllegalArgumentException("Negative length for BitArray"); } this.length = length; repn = new byte[(length + BITS_PER_UNIT - 1) / BITS_PER_UNIT]; } /** * Creates a BitArray of the specified size, initialized from the * specified byte array. The most significant bit of a[0] gets * index zero in the BitArray. The array a must be large enough * to specify a value for every bit in the BitArray. In other words, * {@code 8*a.length >= length}. */ public BitArray(int length, byte[] a) throws IllegalArgumentException { if (length < 0) { throw new IllegalArgumentException("Negative length for BitArray"); } if (a.length * BITS_PER_UNIT < length) { throw new IllegalArgumentException("Byte array too short to represent " + "bit array of given length"); } this.length = length; int repLength = ((length + BITS_PER_UNIT - 1) / BITS_PER_UNIT); int unusedBits = repLength * BITS_PER_UNIT - length; byte bitMask = (byte) (0xFF << unusedBits); /* normalize the representation: 1. discard extra bytes 2. zero out extra bits in the last byte */ repn = new byte[repLength]; System.arraycopy(a, 0, repn, 0, repLength); if (repn.length > 0) repn[repn.length - 1] = (byte) (repn[repn.length - 1] & bitMask); } /** * Create a BitArray whose bits are those of the given array * of Booleans. */ public BitArray(boolean[] bits) { length = bits.length; repn = new byte[(length + 7) / 8]; for (int i = 0; i < length; i++) { set(i, bits[i]); } } /** * Copy constructor (for cloning). */ private BitArray(BitArray ba) { length = ba.length; repn = ba.repn.clone(); } /** * Returns the indexed bit in this BitArray. */ public boolean get(int index) throws ArrayIndexOutOfBoundsException { if (index < 0 || index >= length) { throw new ArrayIndexOutOfBoundsException(Integer.toString(index)); } return (repn[subscript(index)] & position(index)) != 0; } /** * Sets the indexed bit in this BitArray. */ public void set(int index, boolean value) throws ArrayIndexOutOfBoundsException { if (index < 0 || index >= length) { throw new ArrayIndexOutOfBoundsException(Integer.toString(index)); } int idx = subscript(index); int bit = position(index); if (value) { repn[idx] |= bit; } else { repn[idx] &= ~bit; } } /** * Returns the length of this BitArray. */ public int length() { return length; } /** * Returns a Byte array containing the contents of this BitArray. * The bit stored at index zero in this BitArray will be copied * into the most significant bit of the zeroth element of the * returned byte array. The last byte of the returned byte array * will be contain zeros in any bits that do not have corresponding * bits in the BitArray. (This matters only if the BitArray's size * is not a multiple of 8.) */ public byte[] toByteArray() { return repn.clone(); } @Override public boolean equals(Object obj) { if (obj == this) return true; if (obj == null || !(obj instanceof BitArray)) return false; BitArray ba = (BitArray) obj; if (ba.length != length) return false; for (int i = 0; i < repn.length; i += 1) { if (repn[i] != ba.repn[i]) return false; } return true; } /** * Return a boolean array with the same bit values a this BitArray. */ public boolean[] toBooleanArray() { boolean[] bits = new boolean[length]; for (int i = 0; i < length; i++) { bits[i] = get(i); } return bits; } /** * Returns a hash code value for this bit array. * * @return a hash code value for this bit array. */ @Override public int hashCode() { int hashCode = 0; for (int i = 0; i < repn.length; i++) hashCode = 31 * hashCode + repn[i]; return hashCode ^ length; } @Override public Object clone() { return new BitArray(this); } private static final byte[][] NYBBLE = { { (byte) '0', (byte) '0', (byte) '0', (byte) '0' }, { (byte) '0', (byte) '0', (byte) '0', (byte) '1' }, { (byte) '0', (byte) '0', (byte) '1', (byte) '0' }, { (byte) '0', (byte) '0', (byte) '1', (byte) '1' }, { (byte) '0', (byte) '1', (byte) '0', (byte) '0' }, { (byte) '0', (byte) '1', (byte) '0', (byte) '1' }, { (byte) '0', (byte) '1', (byte) '1', (byte) '0' }, { (byte) '0', (byte) '1', (byte) '1', (byte) '1' }, { (byte) '1', (byte) '0', (byte) '0', (byte) '0' }, { (byte) '1', (byte) '0', (byte) '0', (byte) '1' }, { (byte) '1', (byte) '0', (byte) '1', (byte) '0' }, { (byte) '1', (byte) '0', (byte) '1', (byte) '1' }, { (byte) '1', (byte) '1', (byte) '0', (byte) '0' }, { (byte) '1', (byte) '1', (byte) '0', (byte) '1' }, { (byte) '1', (byte) '1', (byte) '1', (byte) '0' }, { (byte) '1', (byte) '1', (byte) '1', (byte) '1' } }; private static final int BYTES_PER_LINE = 8; /** * Returns a string representation of this BitArray. */ @Override public String toString() { ByteArrayOutputStream out = new ByteArrayOutputStream(); for (int i = 0; i < repn.length - 1; i++) { out.write(NYBBLE[(repn[i] >> 4) & 0x0F], 0, 4); out.write(NYBBLE[repn[i] & 0x0F], 0, 4); if (i % BYTES_PER_LINE == BYTES_PER_LINE - 1) { out.write('\n'); } else { out.write(' '); } } // in last byte of repn, use only the valid bits for (int i = BITS_PER_UNIT * (repn.length - 1); i < length; i++) { out.write(get(i) ? '1' : '0'); } return new String(out.toByteArray()); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/ByteArrayLexOrder.java000066400000000000000000000042021412550063600306440ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.util.Comparator; /** * Compare two byte arrays in lexicographical order. * * @version 1.4 97/12/10 * @author D. N. Hoover */ public class ByteArrayLexOrder implements Comparator, java.io.Serializable { private static final long serialVersionUID = 1897537410212918669L; /** * Perform lexicographical comparison of two byte arrays, * regarding each byte as unsigned. That is, compare array entries * in order until they differ--the array with the smaller entry * is "smaller". If array entries are * equal till one array ends, then the longer array is "bigger". * * @param bytes1 first byte array to compare. * @param bytes2 second byte array to compare. * @return negative number if {@literal bytes1 < bytes2}, 0 if bytes1 == bytes2, * positive number if {@literal bytes1 > bytes2}. */ @Override public final int compare(byte[] bytes1, byte[] bytes2) { int diff; for (int i = 0; i < bytes1.length && i < bytes2.length; i++) { diff = (bytes1[i] & 0xFF) - (bytes2[i] & 0xFF); if (diff != 0) { return diff; } } // if array entries are equal till the first ends, then the // longer is "bigger" return bytes1.length - bytes2.length; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/ByteArrayTagOrder.java000066400000000000000000000033121412550063600306300ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.util.Comparator; public class ByteArrayTagOrder implements Comparator, java.io.Serializable { private static final long serialVersionUID = -2027007556858126443L; /** * Compare two byte arrays, by the order of their tags, * as defined in ITU-T X.680, sec. 6.4. (First compare * tag classes, then tag numbers, ignoring the constructivity bit.) * * @param bytes1 first byte array to compare. * @param bytes2 second byte array to compare. * @return negative number if {@literal bytes1 < bytes2}, 0 if bytes1 == bytes2, * positive number if {@literal bytes1 > bytes2}. */ @Override public final int compare(byte[] bytes1, byte[] bytes2) { // tag order is same as byte order ignoring any difference in // the constructivity bit (0x02) return (bytes1[0] | 0x20) - (bytes2[0] | 0x20); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/Cert.java000066400000000000000000000277041412550063600262060ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.io.IOException; import java.security.cert.CertificateException; import java.security.cert.X509CRL; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.apache.commons.lang3.ArrayUtils; import org.mozilla.jss.crypto.SignatureAlgorithm; import org.mozilla.jss.netscape.security.pkcs.PKCS7; import org.mozilla.jss.netscape.security.x509.X509CRLImpl; import org.mozilla.jss.netscape.security.x509.X509CertImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Cert { private static Logger logger = LoggerFactory.getLogger(Cert.class); public static final String HEADER = "-----BEGIN CERTIFICATE-----"; public static final String FOOTER = "-----END CERTIFICATE-----"; public static final String PKCS7_HEADER = "-----BEGIN PKCS7-----"; public static final String PKCS7_FOOTER = "-----END PKCS7-----"; // From https://www.rfc-editor.org/rfc/rfc7468.txt public static final String REQUEST_HEADER = "-----BEGIN CERTIFICATE REQUEST-----"; public static final String REQUEST_FOOTER = "-----END CERTIFICATE REQUEST-----"; public static SignatureAlgorithm mapAlgorithmToJss(String algname) { if (algname.equals("MD5withRSA")) return SignatureAlgorithm.RSASignatureWithMD5Digest; else if (algname.equals("MD2withRSA")) return SignatureAlgorithm.RSASignatureWithMD2Digest; else if (algname.equals("SHA1withRSA")) return SignatureAlgorithm.RSASignatureWithSHA1Digest; else if (algname.equals("SHA1withDSA")) return SignatureAlgorithm.DSASignatureWithSHA1Digest; else if (algname.equals("SHA256withRSA")) return SignatureAlgorithm.RSASignatureWithSHA256Digest; else if (algname.equals("SHA384withRSA")) return SignatureAlgorithm.RSASignatureWithSHA384Digest; else if (algname.equals("SHA512withRSA")) return SignatureAlgorithm.RSASignatureWithSHA512Digest; else if (algname.equals("SHA1withEC")) return SignatureAlgorithm.ECSignatureWithSHA1Digest; else if (algname.equals("SHA256withEC")) return SignatureAlgorithm.ECSignatureWithSHA256Digest; else if (algname.equals("SHA384withEC")) return SignatureAlgorithm.ECSignatureWithSHA384Digest; else if (algname.equals("SHA512withEC")) return SignatureAlgorithm.ECSignatureWithSHA512Digest; else if (algname.equals("SHA256withRSA/PSS")) return SignatureAlgorithm.RSAPSSSignatureWithSHA256Digest; else if (algname.equals("SHA384withRSA/PSS")) return SignatureAlgorithm.RSAPSSSignatureWithSHA384Digest; else if (algname.equals("SHA512withRSA/PSS")) return SignatureAlgorithm.RSAPSSSignatureWithSHA512Digest; return null; } public static String stripBrackets(String s) { if (s == null) { return s; } if (s.startsWith(HEADER) && s.endsWith(FOOTER)) { return s.substring(HEADER.length(), s.length() - FOOTER.length()); } if (s.startsWith(PKCS7_HEADER) && s.endsWith(PKCS7_FOOTER)) { return s.substring(PKCS7_HEADER.length(), s.length() - PKCS7_FOOTER.length()); } // To support Thawte's header and footer if ((s.startsWith("-----BEGIN PKCS #7 SIGNED DATA-----")) && (s.endsWith("-----END PKCS #7 SIGNED DATA-----"))) { return (s.substring(35, (s.length() - 33))); } return s; } public static String stripCRLBrackets(String s) { if (s == null) { return s; } if ((s.startsWith("-----BEGIN CERTIFICATE REVOCATION LIST-----")) && (s.endsWith("-----END CERTIFICATE REVOCATION LIST-----"))) { return (s.substring(43, (s.length() - 41))); } return s; } public static String stripCertBrackets(String s) { return stripBrackets(s); } // private static BASE64Decoder mDecoder = new BASE64Decoder(); public static X509CertImpl mapCert(String mime64) throws IOException { mime64 = stripCertBrackets(mime64.trim()); String newval = normalizeCertStr(mime64); // byte rawPub[] = mDecoder.decodeBuffer(newval); byte rawPub[] = Utils.base64decode(newval); X509CertImpl cert = null; try { cert = new X509CertImpl(rawPub); } catch (CertificateException e) { } return cert; } public static X509Certificate[] mapCertFromPKCS7(String mime64) throws IOException { mime64 = stripCertBrackets(mime64.trim()); String newval = normalizeCertStr(mime64); // byte rawPub[] = mDecoder.decodeBuffer(newval); byte rawPub[] = Utils.base64decode(newval); PKCS7 p7 = null; try { p7 = new PKCS7(rawPub); } catch (Exception e) { throw new IOException("Unable to parse PKCS #7 data: " + e.getMessage(), e); } return p7.getCertificates(); } public static X509CRL mapCRL(String mime64) throws IOException { mime64 = stripCRLBrackets(mime64.trim()); String newval = normalizeCertStr(mime64); // byte rawPub[] = mDecoder.decodeBuffer(newval); byte rawPub[] = Utils.base64decode(newval); X509CRL crl = null; try { crl = new X509CRLImpl(rawPub); } catch (Exception e) { } return crl; } public static X509CRL mapCRL1(String mime64) throws IOException { mime64 = stripCRLBrackets(mime64.trim()); byte rawPub[] = Utils.base64decode(mime64); X509CRL crl = null; try { crl = new X509CRLImpl(rawPub); } catch (Exception e) { throw new IOException(e.toString()); } return crl; } public static String normalizeCertStr(String s) { StringBuffer val = new StringBuffer(); for (int i = 0; i < s.length(); i++) { if (s.charAt(i) == '\n') { continue; } else if (s.charAt(i) == '\r') { continue; } else if (s.charAt(i) == '"') { continue; } else if (s.charAt(i) == ' ') { continue; } val.append(s.charAt(i)); } return val.toString(); } public static String normalizeCertStrAndReq(String s) { StringBuffer val = new StringBuffer(); for (int i = 0; i < s.length(); i++) { if (s.charAt(i) == '\n') { continue; } else if (s.charAt(i) == '\r') { continue; } else if (s.charAt(i) == '"') { continue; } val.append(s.charAt(i)); } return val.toString(); } public static byte[] parseCertificate(String cert) { String encoded = normalizeCertStrAndReq(cert); String b64 = stripBrackets(encoded); return Utils.base64decode(b64); } /** * Sorts certificate chain from root to leaf. * * This method sorts an array of certificates (e.g. from a PKCS #7 * data) that represents a certificate chain from root to leaf * according to the subject DNs and issuer DNs. * * The input array is a set of certificates that are part of a * chain but not in specific order. * * The result is a new array that contains the certificate chain * sorted from root to leaf. The input array is unchanged. * * @param certs input array of certificates * @return new array containing sorted certificates */ public static java.security.cert.X509Certificate[] sortCertificateChain(java.security.cert.X509Certificate[] certs) throws Exception { if (certs == null) { return null; } if (certs.length == 0) { return certs; } // lookup map: subject DN -> cert Map certMap = new LinkedHashMap<>(); // hierarchy map: subject DN -> issuer DN Map parentMap = new HashMap<>(); // reverse hierarchy map: issuer DN -> subject DN Map childMap = new HashMap<>(); // build maps for (java.security.cert.X509Certificate cert : certs) { String subjectDN = cert.getSubjectDN().toString(); String issuerDN = cert.getIssuerDN().toString(); if (certMap.containsKey(subjectDN)) { throw new Exception("Duplicate certificate: " + subjectDN); } certMap.put(subjectDN, cert); // ignore self-signed certificate if (subjectDN.equals(issuerDN)) continue; if (childMap.containsKey(issuerDN)) { throw new Exception("Branched chain: " + issuerDN); } parentMap.put(subjectDN, issuerDN); childMap.put(issuerDN, subjectDN); } if (logger.isDebugEnabled()) { logger.debug("Certificates:"); for (String subjectDN : certMap.keySet()) { logger.debug(" - " + subjectDN); String parent = parentMap.get(subjectDN); if (parent != null) logger.debug(" parent: " + parent); String child = childMap.get(subjectDN); if (child != null) logger.debug(" child: " + child); } } // find leaf cert by removing certs that has a child List leafCerts = new ArrayList<>(); leafCerts.addAll(certMap.keySet()); leafCerts.removeAll(childMap.keySet()); if (leafCerts.isEmpty()) { throw new Exception("Unable to find leaf certificate"); } if (leafCerts.size() > 1) { StringBuilder sb = new StringBuilder(); for (String subjectDN : leafCerts) { if (sb.length() > 0) sb.append(", "); sb.append("[" + subjectDN + "]"); } throw new Exception("Multiple leaf certificates: " + sb); } // build sorted chain LinkedList chain = new LinkedList<>(); // start from leaf String current = leafCerts.get(0); while (current != null) { java.security.cert.X509Certificate cert = certMap.get(current); if (cert == null) { // incomplete chain break; } // add to the beginning of chain chain.addFirst(cert); // follow parent to root current = parentMap.get(current); } return chain.toArray(new java.security.cert.X509Certificate[chain.size()]); } public static java.security.cert.X509Certificate[] sortCertificateChain( java.security.cert.X509Certificate[] certs, boolean reverse) throws Exception { certs = sortCertificateChain(certs); if (reverse) { ArrayUtils.reverse(certs); } return certs; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/CertPrettyPrint.java000066400000000000000000000314631412550063600304300ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.security.MessageDigest; import java.security.PublicKey; import java.security.cert.Certificate; import java.text.DateFormat; import java.util.Locale; import java.util.ResourceBundle; import java.util.TimeZone; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.SET; import org.mozilla.jss.pkcs7.ContentInfo; import org.mozilla.jss.pkcs7.SignedData; import org.mozilla.jss.netscape.security.x509.CertificateExtensions; import org.mozilla.jss.netscape.security.x509.CertificateX509Key; import org.mozilla.jss.netscape.security.x509.Extension; import org.mozilla.jss.netscape.security.x509.X509CertImpl; import org.mozilla.jss.netscape.security.x509.X509CertInfo; import org.mozilla.jss.netscape.security.x509.X509Key; /** * This class will display the certificate content in predefined * format. * * @author Jack Pan-Chen * @version $Revision$, $Date$ */ public class CertPrettyPrint { /*========================================================== * constants *==========================================================*/ private final static String CUSTOM_LOCALE = "Custom"; /*========================================================== * variables *==========================================================*/ private X509CertImpl mX509Cert = null; private PrettyPrintFormat pp = null; private byte[] mCert_b = null; /*========================================================== * constructors *==========================================================*/ public CertPrettyPrint(Certificate cert) { if (cert instanceof X509CertImpl) mX509Cert = (X509CertImpl) cert; pp = new PrettyPrintFormat(":"); } public CertPrettyPrint(byte[] certb) { mCert_b = certb; pp = new PrettyPrintFormat(":"); } /*========================================================== * public methods *==========================================================*/ /** * This method return string representation of the certificate * in predefined format using specified client local. I18N Support. * * @param clientLocale Locale to be used for localization * @return string representation of the certificate */ public String toString(Locale clientLocale) { if (mX509Cert != null) return X509toString(clientLocale); else if (mCert_b != null) return pkcs7toString(clientLocale); else return null; } public String pkcs7toString(Locale clientLocale) { StringBuffer content=new StringBuffer(); try { mX509Cert = new X509CertImpl(mCert_b); return toString(clientLocale); } catch (Exception e) { } ContentInfo ci = null; try { ci = (ContentInfo) ASN1Util.decode(ContentInfo.getTemplate(), mCert_b); } catch (Exception e) { return ""; } if (ci.getContentType().equals(ContentInfo.SIGNED_DATA)) { SignedData sd = null; try { sd = (SignedData) ci.getInterpretedContent(); } catch (Exception e) { return ""; } if (sd.hasCertificates()) { SET certs = sd.getCertificates(); for (int i = 0; i < certs.size(); i++) { org.mozilla.jss.pkix.cert.Certificate cert = (org.mozilla.jss.pkix.cert.Certificate) certs.elementAt(i); X509CertImpl certImpl = null; try { certImpl = new X509CertImpl( ASN1Util.encode(cert)); } catch (Exception e) { } CertPrettyPrint print = new CertPrettyPrint(certImpl); content.append(print.toString(Locale.getDefault())); content.append("\n"); } return content.toString(); } } return content.toString(); } public String stripCertBrackets(String s) { if (s == null) { return s; } if ((s.startsWith(Cert.HEADER)) && (s.endsWith(Cert.FOOTER))) { return (s.substring(27, (s.length() - 25))); } // To support Thawte's header and footer if ((s.startsWith("-----BEGIN PKCS #7 SIGNED DATA-----")) && (s.endsWith("-----END PKCS #7 SIGNED DATA-----"))) { return (s.substring(35, (s.length() - 33))); } return s; } public String normalizeCertStr(String s) { StringBuffer val = new StringBuffer(); for (int i = 0; i < s.length(); i++) { if (s.charAt(i) == '\n') { continue; } else if (s.charAt(i) == '\r') { continue; } else if (s.charAt(i) == '"') { continue; } else if (s.charAt(i) == ' ') { continue; } val.append(s.charAt(i)); } return val.toString(); } public String X509toString(Locale clientLocale) { //get I18N resources ResourceBundle resource = ResourceBundle.getBundle( PrettyPrintResources.class.getName()); DateFormat dateFormater = DateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.FULL, clientLocale); //get timezone and timezone ID String tz = " "; String tzid = " "; StringBuffer sb = new StringBuffer(); try { X509CertInfo info = (X509CertInfo) mX509Cert.get( X509CertImpl.NAME + "." + X509CertImpl.INFO); String serial2 = mX509Cert.getSerialNumber().toString(16).toUpperCase(); //get correct instance of key PublicKey pKey = mX509Cert.getPublicKey(); X509Key key = null; if (pKey instanceof CertificateX509Key) { CertificateX509Key certKey = (CertificateX509Key) pKey; key = (X509Key) certKey.get(CertificateX509Key.KEY); } if (pKey instanceof X509Key) { key = (X509Key) pKey; } //take care of spki sb.append(pp.indent(4) + resource.getString( PrettyPrintResources.TOKEN_CERTIFICATE) + "\n"); sb.append(pp.indent(8) + resource.getString( PrettyPrintResources.TOKEN_DATA) + "\n"); sb.append(pp.indent(12) + resource.getString( PrettyPrintResources.TOKEN_VERSION) + " v"); sb.append((mX509Cert.getVersion() + 1) + "\n"); sb.append(pp.indent(12) + resource.getString( PrettyPrintResources.TOKEN_SERIAL) + "0x" + serial2 + "\n"); //XXX I18N Algorithm Name ? sb.append(pp.indent(12) + resource.getString( PrettyPrintResources.TOKEN_SIGALG) + mX509Cert.getSigAlgName() + " - " + mX509Cert.getSigAlgOID() + "\n"); //XXX I18N IssuerDN ? sb.append(pp.indent(12) + resource.getString( PrettyPrintResources.TOKEN_ISSUER) + mX509Cert.getIssuerDN().toString() + "\n"); sb.append(pp.indent(12) + resource.getString( PrettyPrintResources.TOKEN_VALIDITY) + "\n"); String notBefore = dateFormater.format(mX509Cert.getNotBefore()); String notAfter = dateFormater.format(mX509Cert.getNotAfter()); //get timezone and timezone ID if (TimeZone.getDefault() != null) { tz = TimeZone.getDefault().getDisplayName( TimeZone.getDefault().inDaylightTime( mX509Cert.getNotBefore()), TimeZone.SHORT, clientLocale); tzid = TimeZone.getDefault().getID(); } // Specify notBefore if (tz.equals(tzid) || tzid.equals(CUSTOM_LOCALE)) { // Do NOT append timezone ID sb.append(pp.indent(16) + resource.getString( PrettyPrintResources.TOKEN_NOT_BEFORE) + notBefore + "\n"); } else { // Append timezone ID sb.append(pp.indent(16) + resource.getString( PrettyPrintResources.TOKEN_NOT_BEFORE) + notBefore + " " + tzid + "\n"); } // re-get timezone (just in case it is different . . .) if (TimeZone.getDefault() != null) { tz = TimeZone.getDefault().getDisplayName( TimeZone.getDefault().inDaylightTime( mX509Cert.getNotAfter()), TimeZone.SHORT, clientLocale); } // Specify notAfter if (tz.equals(tzid) || tzid.equals(CUSTOM_LOCALE)) { // Do NOT append timezone ID sb.append(pp.indent(16) + resource.getString( PrettyPrintResources.TOKEN_NOT_AFTER) + notAfter + "\n"); } else { // Append timezone ID sb.append(pp.indent(16) + resource.getString( PrettyPrintResources.TOKEN_NOT_AFTER) + notAfter + " " + tzid + "\n"); } //XXX I18N SubjectDN ? sb.append(pp.indent(12) + resource.getString( PrettyPrintResources.TOKEN_SUBJECT) + mX509Cert.getSubjectDN().toString() + "\n"); sb.append(pp.indent(12) + resource.getString( PrettyPrintResources.TOKEN_SPKI) + "\n"); PubKeyPrettyPrint pkpp = new PubKeyPrettyPrint(key); sb.append(pkpp.toString(clientLocale, 16, 16)); //take care of extensions CertificateExtensions extensions = (CertificateExtensions) info.get(X509CertInfo.EXTENSIONS); sb.append(pp.indent(12) + resource.getString( PrettyPrintResources.TOKEN_EXTENSIONS) + "\n"); if (extensions != null) for (int i = 0; i < extensions.size(); i++) { Extension ext = extensions.elementAt(i); ExtPrettyPrint extpp = new ExtPrettyPrint(ext, 16); sb.append(extpp.toString()); } //take care of signature sb.append(pp.indent(8) + resource.getString( PrettyPrintResources.TOKEN_SIGNATURE) + "\n"); //XXX I18N Algorithm Name ? sb.append(pp.indent(12) + resource.getString( PrettyPrintResources.TOKEN_ALGORITHM) + mX509Cert.getSigAlgName() + " - " + mX509Cert.getSigAlgOID() + "\n"); sb.append(pp.indent(12) + resource.getString( PrettyPrintResources.TOKEN_SIGNATURE) + "\n"); sb.append(pp.toHexString(mX509Cert.getSignature(), 16, 16)); // fingerprints String[] hashes = new String[] { "MD2", "MD5", "SHA-1", "SHA-256", "SHA-512" }; StringBuffer certFingerprints = new StringBuffer(); sb.append(pp.indent(8) + "FingerPrint\n"); for (int i = 0; i < hashes.length; i++) { MessageDigest md = MessageDigest.getInstance(hashes[i]); md.update(mX509Cert.getEncoded()); certFingerprints.append(pp.indent(12) + hashes[i] + ":\n" + pp.toHexString(md.digest(), 16, 16)); } sb.append(certFingerprints.toString()); } catch (Exception e) { e.printStackTrace(); } return sb.toString(); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/CrlPrettyPrint.java000066400000000000000000000276661412550063600302650ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.text.DateFormat; import java.util.Iterator; import java.util.Locale; import java.util.ResourceBundle; import java.util.Set; import java.util.TimeZone; import org.mozilla.jss.netscape.security.x509.CRLExtensions; import org.mozilla.jss.netscape.security.x509.Extension; import org.mozilla.jss.netscape.security.x509.RevokedCertificate; import org.mozilla.jss.netscape.security.x509.X509CRLImpl; /** * This class will display the certificate content in predefined * format. * * @author Andrew Wnuk * @version $Revision$, $Date$ */ public class CrlPrettyPrint { /*========================================================== * constants *==========================================================*/ private final static String CUSTOM_LOCALE = "Custom"; /*========================================================== * variables *==========================================================*/ private X509CRLImpl mCRL = null; private PrettyPrintFormat pp = null; /*========================================================== * constructors *==========================================================*/ public CrlPrettyPrint(X509CRLImpl crl) { mCRL = crl; pp = new PrettyPrintFormat(":"); } /*========================================================== * public methods *==========================================================*/ /** * This method return string representation of the certificate * revocation list in predefined format using specified client * local. I18N Support. * * @param clientLocale Locale to be used for localization * @return string representation of the certificate */ public String toString(Locale clientLocale) { return toString(clientLocale, 0, 0, 0); } public String toString(Locale clientLocale, long crlSize, long pageStart, long pageSize) { //get I18N resources ResourceBundle resource = ResourceBundle.getBundle( PrettyPrintResources.class.getName()); DateFormat dateFormater = DateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.FULL, clientLocale); //get timezone and timezone ID String tz = " "; String tzid = " "; StringBuffer sb = new StringBuffer(); try { sb.append(pp.indent(4) + resource.getString( PrettyPrintResources.TOKEN_CRL) + "\n"); sb.append(pp.indent(8) + resource.getString( PrettyPrintResources.TOKEN_DATA) + "\n"); sb.append(pp.indent(12) + resource.getString( PrettyPrintResources.TOKEN_VERSION) + " v"); sb.append((mCRL.getVersion() + 1) + "\n"); sb.append(pp.indent(12) + resource.getString( PrettyPrintResources.TOKEN_SIGALG) + mCRL.getSigAlgName() + " - " + mCRL.getSigAlgOID() + "\n"); sb.append(pp.indent(12) + resource.getString( PrettyPrintResources.TOKEN_ISSUER) + mCRL.getIssuerDN().toString() + "\n"); // Format thisUpdate String thisUpdate = dateFormater.format(mCRL.getThisUpdate()); // get timezone and timezone ID if (TimeZone.getDefault() != null) { tz = TimeZone.getDefault().getDisplayName( TimeZone.getDefault().inDaylightTime( mCRL.getThisUpdate()), TimeZone.SHORT, clientLocale); tzid = TimeZone.getDefault().getID(); } // Specify ThisUpdate if (tz.equals(tzid) || tzid.equals(CUSTOM_LOCALE)) { // Do NOT append timezone ID sb.append(pp.indent(12) + resource.getString( PrettyPrintResources.TOKEN_THIS_UPDATE) + thisUpdate + "\n"); } else { // Append timezone ID sb.append(pp.indent(12) + resource.getString( PrettyPrintResources.TOKEN_THIS_UPDATE) + thisUpdate + " " + tzid + "\n"); } // Check for presence of NextUpdate if (mCRL.getNextUpdate() != null) { // Format nextUpdate String nextUpdate = dateFormater.format(mCRL.getNextUpdate()); // re-get timezone (just in case it is different . . .) if (TimeZone.getDefault() != null) { tz = TimeZone.getDefault().getDisplayName( TimeZone.getDefault().inDaylightTime( mCRL.getNextUpdate()), TimeZone.SHORT, clientLocale); } // Specify NextUpdate if (tz.equals(tzid) || tzid.equals(CUSTOM_LOCALE)) { // Do NOT append timezone ID sb.append(pp.indent(12) + resource.getString( PrettyPrintResources.TOKEN_NEXT_UPDATE) + nextUpdate + "\n"); } else { // Append timezone ID sb.append(pp.indent(12) + resource.getString( PrettyPrintResources.TOKEN_NEXT_UPDATE) + nextUpdate + " " + tzid + "\n"); } } if (crlSize > 0 && pageStart == 0 && pageSize == 0) { sb.append(pp.indent(12) + resource.getString( PrettyPrintResources.TOKEN_REVOKED_CERTIFICATES) + crlSize + "\n"); } else if ((crlSize == 0 && pageStart == 0 && pageSize == 0) || (crlSize > 0 && pageStart > 0 && pageSize > 0)) { sb.append(pp.indent(12) + resource.getString( PrettyPrintResources.TOKEN_REVOKED_CERTIFICATES)); if (crlSize > 0 && pageStart > 0 && pageSize > 0) { long upperLimit = (pageStart + pageSize - 1 > crlSize) ? crlSize : pageStart + pageSize - 1; sb.append("" + pageStart + "-" + upperLimit + " of " + crlSize); } sb.append("\n"); Set revokedCerts = mCRL.getRevokedCertificates(); if (revokedCerts != null) { Iterator i = revokedCerts.iterator(); long l = 1; while ((i.hasNext()) && ((crlSize == 0) || (pageStart + pageSize > l))) { RevokedCertificate revokedCert = i.next(); if ((crlSize == 0) || ((pageStart <= l) && (pageStart + pageSize > l))) { sb.append(pp.indent(16) + resource.getString( PrettyPrintResources.TOKEN_SERIAL) + "0x" + revokedCert.getSerialNumber().toString(16).toUpperCase() + "\n"); String revocationDate = dateFormater.format(revokedCert.getRevocationDate()); // re-get timezone // (just in case it is different . . .) if (TimeZone.getDefault() != null) { tz = TimeZone.getDefault().getDisplayName( TimeZone.getDefault().inDaylightTime( revokedCert.getRevocationDate()), TimeZone.SHORT, clientLocale); } // Specify revocationDate if (tz.equals(tzid) || tzid.equals(CUSTOM_LOCALE)) { // Do NOT append timezone ID sb.append(pp.indent(16) + resource.getString( PrettyPrintResources.TOKEN_REVOCATION_DATE) + revocationDate + "\n"); } else { // Append timezone ID sb.append(pp.indent(16) + resource.getString( PrettyPrintResources.TOKEN_REVOCATION_DATE) + revocationDate + " " + tzid + "\n"); } if (revokedCert.hasExtensions()) { sb.append(pp.indent(16) + resource.getString( PrettyPrintResources.TOKEN_EXTENSIONS) + "\n"); CRLExtensions crlExtensions = revokedCert.getExtensions(); if (crlExtensions != null) { for (int k = 0; k < crlExtensions.size(); k++) { Extension ext = crlExtensions.elementAt(k); ExtPrettyPrint extpp = new ExtPrettyPrint(ext, 20); sb.append(extpp.toString()); } } } } l++; } } } CRLExtensions crlExtensions = mCRL.getExtensions(); if (crlExtensions != null) { sb.append(pp.indent(8) + resource.getString( PrettyPrintResources.TOKEN_EXTENSIONS) + "\n"); for (int k = 0; k < crlExtensions.size(); k++) { Extension ext = crlExtensions.elementAt(k); ExtPrettyPrint extpp = new ExtPrettyPrint(ext, 12); sb.append(extpp.toString()); } } //take care of signature sb.append(pp.indent(8) + resource.getString( PrettyPrintResources.TOKEN_SIGNATURE) + "\n"); //XXX I18N Algorithm Name ? sb.append(pp.indent(12) + resource.getString( PrettyPrintResources.TOKEN_ALGORITHM) + mCRL.getSigAlgName() + " - " + mCRL.getSigAlgOID() + "\n"); sb.append(pp.indent(12) + resource.getString( PrettyPrintResources.TOKEN_SIGNATURE) + "\n"); sb.append(pp.toHexString(mCRL.getSignature(), 16, 16)); } catch (Exception e) { sb.append("\n\n" + pp.indent(4) + resource.getString( PrettyPrintResources.TOKEN_DECODING_ERROR) + "\n\n"); e.printStackTrace(); } return sb.toString(); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/DerEncoder.java000066400000000000000000000024401412550063600273110ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.io.IOException; import java.io.OutputStream; /** * Interface to an object that knows how to write its own DER * encoding to an output stream. * * @version 1.2 97/12/10 * @author D. N. Hoover */ public interface DerEncoder { /** * DER encode this object and write the results to a stream. * * @param out the stream on which the DER encoding is written. */ public void derEncode(OutputStream out) throws IOException; } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/DerInputBuffer.java000066400000000000000000000130101412550063600301560ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.OutputStream; /** * DER input buffer ... this is the main abstraction in the DER library * which actively works with the "untyped byte stream" abstraction. It * does so with impunity, since it's not intended to be exposed to the * anyone who could violate the "typed value stream" DER model and hence * corrupt the input stream of DER values. * * @version 1.11 * @author David Brownell */ class DerInputBuffer extends ByteArrayInputStream implements Cloneable { DerInputBuffer(byte[] buf) { super(buf); } DerInputBuffer(byte[] buf, int offset, int len) { super(buf, offset, len); } DerInputBuffer dup() { try { DerInputBuffer retval = (DerInputBuffer) clone(); retval.mark(Integer.MAX_VALUE); return retval; } catch (CloneNotSupportedException e) { throw new IllegalArgumentException(e.toString()); } } byte[] toByteArray() throws IOException { int len = available(); if (len <= 0) throw new IOException("No Buffer Space Available."); byte[] retval = new byte[len]; System.arraycopy(buf, pos, retval, 0, len); return retval; } int peek() throws IOException { if (pos >= count) throw new IOException("out of data"); else return buf[pos]; } /** * Compares this DerInputBuffer for equality with the specified * object. */ @Override public boolean equals(Object other) { if (other instanceof DerInputBuffer) return equals((DerInputBuffer) other); else return false; } boolean equals(DerInputBuffer other) { if (this == other) return true; int max = this.available(); if (other.available() != max) return false; for (int i = 0; i < max; i++) { if (this.buf[this.pos + i] != other.buf[other.pos + i]) { return false; } } return true; } void truncate(int len) throws IOException { if (len > available()) throw new IOException("insufficient data"); count = pos + len; } /** * Returns the unsigned integer which takes up the specified number * of bytes in this buffer. */ BigInt getUnsigned(int len) throws IOException { if (len > available()) throw new IOException("short read, getInteger"); /* * A prepended zero is used to ensure that the integer is * interpreted as unsigned even when the high order bit is * zero. We don't support signed BigInts. * * Fix this here ... BigInts aren't expected to have these, * and stuff like signing (sigsize = f(modulus)) misbehaves. */ if (len > 1 && buf[pos] == 0) { len--; skip(1); } /* * Consume the rest of the buffer, returning its value as * an unsigned integer. */ byte[] bytes = new byte[len]; System.arraycopy(buf, pos, bytes, 0, len); skip(len); return new BigInt(bytes); } /** * Returns the bit string which takes up the rest of this buffer. * This bit string must be byte-aligned. */ byte[] getBitString() { if (pos >= count || buf[pos] != 0) return null; /* * Just copy the data into an aligned, padded octet buffer, * and consume the rest of the buffer. */ int len = available(); byte[] retval = new byte[len - 1]; System.arraycopy(buf, pos + 1, retval, 0, len - 1); pos = count; return retval; } /** * Returns the bit string which takes up the rest of this buffer. * The bit string need not be byte-aligned. */ BitArray getUnalignedBitString() { if (pos >= count) return null; /* * Just copy the data into an aligned, padded octet buffer, * and consume the rest of the buffer. */ int len = available(); byte[] bits = new byte[len - 1]; int length = bits.length * 8 - buf[pos]; // number of valid bits System.arraycopy(buf, pos + 1, bits, 0, len - 1); BitArray bitArray = new BitArray(length, bits); pos = count; return bitArray; } /** * Package-access method to optimize output operations */ void dump(OutputStream out, int length) throws IOException { if (count < mark + length) throw new IOException("short DER value (encode)"); out.write(buf, mark, length); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/DerInputStream.java000066400000000000000000000544401412550063600302140ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.io.IOException; import java.io.InputStream; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; import java.util.Vector; /** * A DER input stream, used for parsing ASN.1 DER-encoded data such as * that found in X.509 certificates. DER is a subset of BER/1, which has * the advantage that it allows only a single encoding of primitive data. * (High level data such as dates still support many encodings.) That is, * it uses the "Definite" Encoding Rules (DER) not the "Basic" ones (BER). * *

* Note that, like BER/1, DER streams are streams of explicitly tagged data values. Accordingly, this programming * interface does not expose any variant of the java.io.InputStream interface, since that kind of input stream holds * untagged data values and using that I/O model could prevent correct parsing of the DER data. * *

* At this time, this class supports only a subset of the types of DER data encodings which are defined. That subset is * sufficient for parsing most X.509 certificates. * * @version 1.35 * * @author David Brownell * @author Amit Kapoor * @author Hemma Prafullchandra */ public class DerInputStream { /* * This version only supports fully buffered DER. This is easy to * work with, though if large objects are manipulated DER becomes * awkward to deal with. That's where BER is useful, since BER * handles streaming data relatively well. */ DerInputBuffer buffer; /** * Create a DER input stream from a data buffer. The buffer is not * copied, it is shared. Accordingly, the buffer should be treated * as read-only. * * @param data the buffer from which to create the string (CONSUMED) */ public DerInputStream(byte[] data) { buffer = new DerInputBuffer(data); buffer.mark(Integer.MAX_VALUE); } /** * Create a DER input stream from part of a data buffer. * The buffer is not copied, it is shared. Accordingly, the * buffer should be treated as read-only. * * @param data the buffer from which to create the string (CONSUMED) * @param offset the first index of data which will * be read as DER input in the new stream * @param len how long a chunk of the buffer to use, * starting at "offset" */ public DerInputStream(byte[] data, int offset, int len) { buffer = new DerInputBuffer(data, offset, len); buffer.mark(Integer.MAX_VALUE); } DerInputStream(DerInputBuffer buf) { buffer = buf; buffer.mark(Integer.MAX_VALUE); } /** * Creates a new DER input stream from part of this input stream. * * @param len how long a chunk of the current input stream to use, * starting at the current position. * @param do_skip true if the existing data in the input stream should * be skipped. If this value is false, the next data read * on this stream and the newly created stream will be the * same. */ public DerInputStream subStream(int len, boolean do_skip) throws IOException { DerInputBuffer newbuf = buffer.dup(); newbuf.truncate(len); if (do_skip) buffer.skip(len); return new DerInputStream(newbuf); } /** * Return what has been written to this DerInputStream * as a byte array. Useful for debugging. * @throws IOException */ public byte[] toByteArray() throws IOException { return buffer.toByteArray(); } /* * PRIMITIVES -- these are "universal" ASN.1 simple types. * * INTEGER, BIT STRING, OCTET STRING, NULL * OBJECT IDENTIFIER, SEQUENCE (OF), SET (OF) * PrintableString, T61String, IA5String, UTCTime */ /** * Get an (unsigned) integer from the input stream. */ public BigInt getInteger() throws IOException { if (buffer.read() != DerValue.tag_Integer) throw new IOException("DER input, Integer tag error"); return buffer.getUnsigned(getLength(buffer)); } /** * Get a bit string from the input stream. Only octet-aligned * bitstrings (multiples of eight bits in length) are handled * by this method. */ public byte[] getBitString() throws IOException { if (buffer.read() != DerValue.tag_BitString) throw new IOException("DER input not an bit string"); int length = getLength(buffer); /* * This byte affects alignment and padding (for the last byte). * Use getUnalignedBitString() for none 8-bit aligned bit strings. */ if (buffer.read() != 0) return null; length--; /* * Just read the data into an aligned, padded octet buffer. */ byte[] retval = new byte[length]; if (buffer.read(retval) != length) throw new IOException("short read of DER bit string"); return retval; } /** * Get a bit string from the input stream. The bit string need * not be byte-aligned. */ public BitArray getUnalignedBitString() throws IOException { if (buffer.read() != DerValue.tag_BitString) throw new IOException("DER input not a bit string"); int length = getLength(buffer) - 1; /* * First byte = number of excess bits in the last octet of the * representation. */ int validBits = length * 8 - buffer.read(); byte[] repn = new byte[length]; if (buffer.read(repn) != length) throw new IOException("short read of DER bit string"); return new BitArray(validBits, repn); } /** * Returns an ASN.1 OCTET STRING from the input stream. */ public byte[] getOctetString() throws IOException { if (buffer.read() != DerValue.tag_OctetString) throw new IOException("DER input not an octet string"); int length = getLength(buffer); byte[] retval = new byte[length]; if (buffer.read(retval) != length) throw new IOException("short read of DER octet string"); return retval; } /** * Returns the asked number of bytes from the input stream. */ public void getBytes(byte[] val) throws IOException { if (val.length != 0) { if (buffer.read(val) != val.length) { throw new IOException("short read of DER octet string"); } } } /** * Reads an encoded null value from the input stream. */ public void getNull() throws IOException { if (buffer.read() != DerValue.tag_Null || buffer.read() != 0) throw new IOException("getNull, bad data"); } /** * Reads an X.200 style Object Identifier from the stream. */ public ObjectIdentifier getOID() throws IOException { return new ObjectIdentifier(this); } /** * Return a sequence of encoded entities. ASN.1 sequences are * ordered, and they are often used, like a "struct" in C or C++, * to group data values. They may have optional or context * specific values. * * @param startLen guess about how long the sequence will be * (used to initialize an auto-growing data structure) * @return array of the values in the sequence */ public DerValue[] getSequence(int startLen) throws IOException { int b = buffer.read(); if (b != DerValue.tag_Sequence) throw new IOException("Sequence tag error " + b); return readVector(startLen); } public void skipSequence(int startLen) throws IOException { int b = buffer.read(); if (b != DerValue.tag_Sequence) throw new IOException("Sequence tag error " + b); int len = getLength(buffer); buffer.skip(len); } /** * Return a set of encoded entities. ASN.1 sets are unordered, * though DER may specify an order for some kinds of sets (such * as the attributes in an X.500 relative distinguished name) * to facilitate binary comparisons of encoded values. * * @param startLen guess about how large the set will be * (used to initialize an auto-growing data structure) * @return array of the values in the sequence */ public DerValue[] getSet(int startLen) throws IOException { if (buffer.read() != DerValue.tag_Set) throw new IOException("Set tag error"); return readVector(startLen); } /** * Return a set of encoded entities. ASN.1 sets are unordered, * though DER may specify an order for some kinds of sets (such * as the attributes in an X.500 relative distinguished name) * to facilitate binary comparisons of encoded values. * * @param startLen guess about how large the set will be * (used to initialize an auto-growing data structure) * @param implicit if true tag is assumed implicit. * @return array of the values in the sequence */ public DerValue[] getSet(int startLen, boolean implicit) throws IOException { int tag = buffer.read(); if (!implicit) { if (tag != DerValue.tag_Set) { throw new IOException("Set tag error"); } } return (readVector(startLen)); } /* * Read a "vector" of values ... set or sequence have the * same encoding, except for the initial tag, so both use * this same helper routine. */ protected DerValue[] readVector(int startLen) throws IOException { int len = getLength(buffer); DerInputStream newstr; if (len == 0) // return empty array instead of null, which should be // used only for missing optionals return new DerValue[0]; /* * Create a temporary stream from which to read the data, * unless it's not really needed. */ if (buffer.available() == len) newstr = this; else newstr = subStream(len, true); /* * Pull values out of the stream. */ Vector vec = new Vector(startLen); DerValue value; do { value = new DerValue(newstr.buffer); vec.addElement(value); } while (newstr.available() > 0); if (newstr.available() != 0) throw new IOException("extra data at end of vector"); /* * Now stick them into the array we're returning. */ int i, max = vec.size(); DerValue[] retval = new DerValue[max]; for (i = 0; i < max; i++) retval[i] = vec.elementAt(i); return retval; } /** * Get a single DER-encoded value from the input stream. * It can often be useful to pull a value from the stream * and defer parsing it. For example, you can pull a nested * sequence out with one call, and only examine its elements * later when you really need to. */ public DerValue getDerValue() throws IOException { return new DerValue(buffer); } public String getPrintableString() throws IOException { return (new DerValue(buffer)).getPrintableString(); } public String getT61String() throws IOException { return (new DerValue(buffer)).getT61String(); } public String getIA5String() throws IOException { return (new DerValue(buffer)).getIA5String(); } public String getBMPString() throws IOException { return (new DerValue(buffer)).getBMPString(); } public String getUniversalString() throws IOException { return (new DerValue(buffer)).getUniversalString(); } public String getDirectoryString() throws IOException { return (new DerValue(buffer)).getDirectoryString(); } /** * Get a UTC encoded time value from the input stream. */ public Date getUTCTime() throws IOException { if (buffer.read() != DerValue.tag_UtcTime) throw new IOException("DER input, UTCtime tag invalid "); if (buffer.available() < 11) throw new IOException("DER input, UTCtime short input"); int len = getLength(buffer); if (len < 11 || len > 17) throw new IOException("DER getUTCTime length error"); /* * UTC time encoded as ASCII chars, YYMMDDhhmmss. * If YY <= 50, we assume 20YY; * if YY > 50, we assume 19YY, as per IETF-PKIX part I. */ int year, month, day, hour, minute, second; year = 10 * Character.digit((char) buffer.read(), 10); year += Character.digit((char) buffer.read(), 10); if (year <= 50) // origin 2000 year += 2000; else year += 1900; // origin 1900 month = 10 * Character.digit((char) buffer.read(), 10); month += Character.digit((char) buffer.read(), 10); month -= 1; // months are 0-11 day = 10 * Character.digit((char) buffer.read(), 10); day += Character.digit((char) buffer.read(), 10); hour = 10 * Character.digit((char) buffer.read(), 10); hour += Character.digit((char) buffer.read(), 10); minute = 10 * Character.digit((char) buffer.read(), 10); minute += Character.digit((char) buffer.read(), 10); len -= 10; /** * We allow for non-encoded seconds, even though the * IETF-PKIX specification says that the seconds should * always be encoded even if it is zero. */ if (len == 3 || len == 7) { second = 10 * Character.digit((char) buffer.read(), 10); second += Character.digit((char) buffer.read(), 10); len -= 2; } else second = 0; if (month < 0 || day <= 0 || month > 11 || day > 31 || hour >= 24 || minute >= 60 || second >= 60) throw new IOException("Parse UTC time, invalid format"); Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); cal.set(year, month, day, hour, minute, second); cal.set(Calendar.MILLISECOND, 0); /* To clear millisecond field */ cal.set(Calendar.ERA, GregorianCalendar.AD); Date readDate = cal.getTime(); long utcTime = readDate.getTime(); /* * Finally, "Z" or "+hhmm" or "-hhmm" ... offsets change hhmm */ if (!(len == 1 || len == 5)) throw new IOException("Parse UTC time, invalid offset"); switch (buffer.read()) { case '+': { int Htmp = 10 * Character.digit((char) buffer.read(), 10); Htmp += Character.digit((char) buffer.read(), 10); int Mtmp = 10 * Character.digit((char) buffer.read(), 10); Mtmp += Character.digit((char) buffer.read(), 10); if (Htmp >= 24 || Mtmp >= 60) throw new IOException("Parse UTCtime, +hhmm"); utcTime += ((Htmp * 60) + Mtmp) * 60 * 1000L; } break; case '-': { int Htmp = 10 * Character.digit((char) buffer.read(), 10); Htmp += Character.digit((char) buffer.read(), 10); int Mtmp = 10 * Character.digit((char) buffer.read(), 10); Mtmp += Character.digit((char) buffer.read(), 10); if (Htmp >= 24 || Mtmp >= 60) throw new IOException("Parse UTCtime, -hhmm"); utcTime -= ((Htmp * 60) + Mtmp) * 60 * 1000L; } break; case 'Z': break; default: throw new IOException("Parse UTCtime, garbage offset"); } readDate.setTime(utcTime); return readDate; } /** * Get a Generalized encoded time value from the input stream. */ public Date getGeneralizedTime() throws IOException { if (buffer.read() != DerValue.tag_GeneralizedTime) throw new IOException("DER input, GeneralizedTime tag invalid "); if (buffer.available() < 13) throw new IOException("DER input, GeneralizedTime short input"); int len = getLength(buffer); /* * Generalized time encoded as ASCII chars, YYYYMMDDhhmm[ss] */ int year, month, day, hour, minute, second; year = 1000 * Character.digit((char) buffer.read(), 10); year += 100 * Character.digit((char) buffer.read(), 10); year += 10 * Character.digit((char) buffer.read(), 10); year += Character.digit((char) buffer.read(), 10); month = 10 * Character.digit((char) buffer.read(), 10); month += Character.digit((char) buffer.read(), 10); month -= 1; // Calendar months are 0-11 day = 10 * Character.digit((char) buffer.read(), 10); day += Character.digit((char) buffer.read(), 10); hour = 10 * Character.digit((char) buffer.read(), 10); hour += Character.digit((char) buffer.read(), 10); minute = 10 * Character.digit((char) buffer.read(), 10); minute += Character.digit((char) buffer.read(), 10); len -= 12; /** * We allow for non-encoded seconds, even though the * IETF-PKIX specification says that the seconds should * always be encoded even if it is zero. */ if (len == 3 || len == 7) { second = 10 * Character.digit((char) buffer.read(), 10); second += Character.digit((char) buffer.read(), 10); len -= 2; } else second = 0; if (month < 0 || day <= 0 || month > 11 || day > 31 || hour >= 24 || minute >= 60 || second >= 60) throw new IOException("Parse Generalized time, invalid format"); /* Shouldn't this construct a Gregorian calendar directly??? * We don't really want locale dependant processing here */ Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); cal.set(year, month, day, hour, minute, second); cal.set(Calendar.MILLISECOND, 0); /* To clear millisecond field */ cal.set(Calendar.ERA, GregorianCalendar.AD); Date readDate = cal.getTime(); long utcTime = readDate.getTime(); /* * Finally, "Z" or "+hhmm" or "-hhmm" ... offsets change hhmm */ if (!(len == 1 || len == 5)) throw new IOException("Parse Generalized time, invalid offset"); switch (buffer.read()) { case '+': { int Htmp = 10 * Character.digit((char) buffer.read(), 10); Htmp += Character.digit((char) buffer.read(), 10); int Mtmp = 10 * Character.digit((char) buffer.read(), 10); Mtmp += Character.digit((char) buffer.read(), 10); if (Htmp >= 24 || Mtmp >= 60) throw new IOException("Parse GeneralizedTime, +hhmm"); utcTime += ((Htmp * 60) + Mtmp) * 60 * 1000L; } break; case '-': { int Htmp = 10 * Character.digit((char) buffer.read(), 10); Htmp += Character.digit((char) buffer.read(), 10); int Mtmp = 10 * Character.digit((char) buffer.read(), 10); Mtmp += Character.digit((char) buffer.read(), 10); if (Htmp >= 24 || Mtmp >= 60) throw new IOException("Parse GeneralizedTime, -hhmm"); utcTime -= ((Htmp * 60) + Mtmp) * 60 * 1000L; } break; case 'Z': break; default: throw new IOException("Parse GeneralizedTime, garbage offset"); } readDate.setTime(utcTime); return readDate; } /* * Get a byte from the input stream. */ // package private int getByte() throws IOException { return (0x00ff & buffer.read()); } public int peekByte() throws IOException { return buffer.peek(); } // package private int getLength() throws IOException { return getLength(buffer); } /* * Get a length from the input stream, allowing for at most 32 bits of * encoding to be used. (Not the same as getting a tagged integer!) */ static int getLength(InputStream in) throws IOException { int value, tmp; tmp = in.read(); if ((tmp & 0x080) == 0x00) { // 1 byte datum? value = tmp; } else { // no, more ... tmp &= 0x07f; /* * NOTE: tmp == 0 indicates BER encoded data. * tmp > 4 indicates more than 4Gb of data. */ if (tmp <= 0 || tmp > 4) throw new IOException("DerInput.getLength(): lengthTag=" + tmp + ", " + ((tmp == 0) ? "Indefinite length encoding not supported" + " or incorrect DER encoding." : "too big.")); for (value = 0; tmp > 0; tmp--) { value <<= 8; value += 0x0ff & in.read(); } } return value; } /** * Mark the current position in the buffer, so that * a later call to reset will return here. */ public void mark(int value) { buffer.mark(value); } /** * Return to the position of the last mark call. A mark is implicitly set at the beginning of * the stream when it is created. */ public void reset() { buffer.reset(); } /** * Returns the number of bytes available for reading. * This is most useful for testing whether the stream is * empty. */ public int available() { return buffer.available(); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/DerOutputStream.java000066400000000000000000000543621412550063600304200ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.CharsetEncoder; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Calendar; import java.util.Comparator; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; /** * Output stream marshaling DER-encoded data. This is eventually provided * in the form of a byte array; there is no advance limit on the size of * that byte array. * *

* At this time, this class supports only a subset of the types of DER data encodings which are defined. That subset is * sufficient for generating most X.509 certificates. * * @version 1.32 * * @author David Brownell * @author Amit Kapoor * @author Hemma Prafullchandra */ public class DerOutputStream extends ByteArrayOutputStream implements DerEncoder { /** * Construct an DER output stream. * * @param size how large a buffer to preallocate. */ public DerOutputStream(int size) { super(size); } /** * Construct an DER output stream. */ public DerOutputStream() { } /** * Writes tagged, pre-marshaled data. This calcuates and encodes * the length, so that the output data is the standard triple of * { tag, length, data } used by all DER values. * * @param tag the DER value tag for the data, such as DerValue.tag_Sequence * @param buf buffered data, which must be DER-encoded */ public void write(byte tag, byte[] buf) throws IOException { write(tag); putLength(buf.length); write(buf, 0, buf.length); } /** * Writes tagged data using buffer-to-buffer copy. As above, * this writes a standard DER record. This is often used when * efficiently encapsulating values in sequences. * * @param tag the DER value tag for the data, such as DerValue.tag_Sequence * @param out buffered data */ public void write(byte tag, DerOutputStream out) throws IOException { write(tag); putLength(out.count); write(out.buf, 0, out.count); } /** * Writes implicitly tagged data using buffer-to-buffer copy. As above, * this writes a standard DER record. This is often used when * efficiently encapsulating implicitly tagged values. * * @param tag the DER value of the context-specific tag that replaces * original tag of the value in the output , such as in *

     *  {@literal } [N] IMPLICIT {@literal }
     * 
* * For example, FooLength [1] IMPLICIT INTEGER, with value=4; * would be encoded as "81 01 04" whereas in explicit * tagging it would be encoded as "A1 03 02 01 04". * Notice that the tag is A1 and not 81, this is because with * explicit tagging the form is always constructed. * @param value original value being implicitly tagged */ public void writeImplicit(byte tag, DerOutputStream value) throws IOException { write(tag); write(value.buf, 1, value.count - 1); } /** * Marshals pre-encoded DER value onto the output stream. */ public void putDerValue(DerValue val) throws IOException { val.encode(this); } /* * PRIMITIVES -- these are "universal" ASN.1 simple types. * * BOOLEAN, INTEGER, BIT STRING, OCTET STRING, NULL * OBJECT IDENTIFIER, SEQUENCE(OF), SET(OF) * PrintableString, T61String, IA5String, UTCTime */ /** * Marshals a DER boolean on the output stream. */ public void putBoolean(boolean val) throws IOException { write(DerValue.tag_Boolean); putLength(1); if (val) { write(0xff); } else { write(0); } } /** * Marshals a DER unsigned integer on the output stream. */ public void putInteger(BigInt i) throws IOException { putUnsignedInteger(i.toByteArray()); } /** * Marshals a DER unsigned integer on the output stream. */ public void putUnsignedInteger(byte[] integerBytes) throws IOException { write(DerValue.tag_Integer); if ((integerBytes[0] & 0x080) != 0) { /* * prepend zero so it's not read as a negative number */ putLength(integerBytes.length + 1); write(0); } else putLength(integerBytes.length); write(integerBytes, 0, integerBytes.length); } /** * Marshals a DER enumerated value on the output stream. */ public void putEnumerated(int i) throws IOException { write(DerValue.tag_Enumerated); int bytemask = 0xff000000; int signmask = 0x80000000; int length; if ((i & 0x80000000) != 0) { // negative case for (length = 4; length > 1; --length) { if ((i & bytemask) != bytemask) break; bytemask = bytemask >>> 8; signmask = signmask >>> 8; } if ((i & signmask) == 0) { // ensure negative case putLength(length + 1); write(0xff); } else { putLength(length); } // unrolled loop switch (length) { case 4: write((byte) (i >>> 24)); case 3: write((byte) (i >>> 16)); case 2: write((byte) (i >>> 8)); case 1: write((byte) i); } } else { // positive case for (length = 4; length > 1; --length) { if ((i & bytemask) != 0) break; bytemask = bytemask >>> 8; signmask = signmask >>> 8; } if ((i & signmask) != 0) { // ensure posititive case putLength(length + 1); write(0x00); } else { putLength(length); } // unrolled loop switch (length) { case 4: write((byte) (i >>> 24)); case 3: write((byte) (i >>> 16)); case 2: write((byte) (i >>> 8)); case 1: write((byte) i); } } } /** * Marshals a DER bit string on the output stream. The bit * string must be byte-aligned. * * @param bits the bit string, MSB first */ public void putBitString(byte[] bits) throws IOException { write(DerValue.tag_BitString); putLength(bits.length + 1); write(0); // all of last octet is used write(bits); } /** * Converts a boolean array to a BitArray. Trims trailing 0 bits * in accordance with DER encoding standard. We assume the input is not * null. */ private static BitArray toBitArray(boolean[] bitString) { if (bitString.length == 0) { return new BitArray(bitString); } // find index of last 1 bit. -1 if there aren't any int i; for (i = bitString.length - 1; i >= 0; i--) { if (bitString[i]) { break; } } int length = i + 1; // if length changed, copy to new appropriately-sized array if (length != bitString.length) { boolean[] newBitString = new boolean[length]; System.arraycopy(bitString, 0, newBitString, 0, length); bitString = newBitString; } return new BitArray(bitString); } /** * Converts bit string to a BitArray, stripping off trailing 0 bits. * We assume that the bit string is not null. */ private static BitArray toBitArray(byte[] bitString) { // compute length in bits of bit string int length, i; int maxIndex = 0; if (bitString.length == 0) { return new BitArray(0, bitString); } // find the index of the last byte with a 1 bit for (i = 0; i < bitString.length; i++) { if (bitString[i] != 0) { maxIndex = i; } } byte lastByte = bitString[maxIndex]; length = (maxIndex + 1) * 8; // maximum, might reduce in next step // now find the last 1 bit in this last byte for (i = 1; i <= 0x80; i <<= 1) { if ((lastByte & i) == 0) { length--; } else { break; } } return new BitArray(length, bitString); } /** * Marshals a DER bit string on the output stream. * The bit strings need not be byte-aligned. * * @param ba the bit string, MSB first */ public void putUnalignedBitString(BitArray ba) throws IOException { byte[] bits = ba.toByteArray(); write(DerValue.tag_BitString); putLength(bits.length + 1); write(bits.length * 8 - ba.length()); // excess bits in last octet write(bits); } /** * Marshals a DER bit string on the output stream. * All trailing 0 bits will be stripped off in accordance with DER * encoding. * * @param bitString the bit string, MSB first */ public void putUnalignedBitString(byte[] bitString) throws IOException { putUnalignedBitString(toBitArray(bitString)); } /** * Marshals a DER bit string on the output stream. * All trailing 0 bits will be stripped off in accordance with DER * encoding. * * @param bitString the bit string as an array of booleans. */ public void putUnalignedBitString(boolean[] bitString) throws IOException { putUnalignedBitString(toBitArray(bitString)); } /** * DER-encodes an ASN.1 OCTET STRING value on the output stream. * * @param octets the octet string */ public void putOctetString(byte[] octets) throws IOException { write(DerValue.tag_OctetString, octets); } /** * Marshals a DER "null" value on the output stream. These are * often used to indicate optional values which have been omitted. */ public void putNull() throws IOException { write(DerValue.tag_Null); putLength(0); } /** * Marshals an object identifier (OID) on the output stream. * Corresponds to the ASN.1 "OBJECT IDENTIFIER" construct. */ public void putOID(ObjectIdentifier oid) throws IOException { oid.encode(this); } /** * Marshals a sequence on the output stream. This supports both * the ASN.1 "SEQUENCE" (zero to N values) and "SEQUENCE OF" * (one to N values) constructs. */ public void putSequence(DerValue[] seq) throws IOException { DerOutputStream bytes = new DerOutputStream(); int i; for (i = 0; i < seq.length; i++) seq[i].encode(bytes); write(DerValue.tag_Sequence, bytes); } /** * Marshals the contents of a set on the output stream without * ordering the elements. Ok for BER encoding, but not for DER * encoding. * * For DER encoding, use orderedPutSet() or orderedPutSetOf(). */ public void putSet(DerValue[] set) throws IOException { DerOutputStream bytes = new DerOutputStream(); int i; for (i = 0; i < set.length; i++) set[i].encode(bytes); write(DerValue.tag_Set, bytes); } /** * NSCP : * Like putOrderSetOf, except not sorted. * This may defy DER encoding but is needed for compatibility * with communicator. */ public void putSet(byte tag, DerEncoder[] set) throws IOException { putOrderedSet(tag, set, null); } /** * Marshals the contents of a set on the output stream. Sets * are semantically unordered, but DER requires that encodings of * set elements be sorted into ascending lexicographical order * before being output. Hence sets with the same tags and * elements have the same DER encoding. * * This method supports the ASN.1 "SET OF" construct, but not * "SET", which uses a different order. */ public void putOrderedSetOf(byte tag, DerEncoder[] set) throws IOException { putOrderedSet(tag, set, lexOrder); } /** * Marshals the contents of a set on the output stream. Sets * are semantically unordered, but DER requires that encodings of * set elements be sorted into ascending tag order * before being output. Hence sets with the same tags and * elements have the same DER encoding. * * This method supports the ASN.1 "SET" construct, but not * "SET OF", which uses a different order. */ public void putOrderedSet(byte tag, DerEncoder[] set) throws IOException { putOrderedSet(tag, set, tagOrder); } /** * Lexicographical order comparison on byte arrays, for ordering * elements of a SET OF objects in DER encoding. */ private static ByteArrayLexOrder lexOrder = new ByteArrayLexOrder(); /** * Tag order comparison on byte arrays, for ordering elements of * SET objects in DER encoding. */ private static ByteArrayTagOrder tagOrder = new ByteArrayTagOrder(); /** * Marshals a the contents of a set on the output stream with the * encodings of its sorted in increasing order. * * @param order the order to use when sorting encodings of components. */ private void putOrderedSet(byte tag, DerEncoder[] set, Comparator order) throws IOException { DerOutputStream[] streams = new DerOutputStream[set.length]; for (int i = 0; i < set.length; i++) { streams[i] = new DerOutputStream(); set[i].derEncode(streams[i]); } // order the element encodings byte[][] bufs = new byte[streams.length][]; for (int i = 0; i < streams.length; i++) { bufs[i] = streams[i].toByteArray(); } if (order != null) { Arrays.sort(bufs, order); } DerOutputStream bytes = new DerOutputStream(); for (int i = 0; i < streams.length; i++) { bytes.write(bufs[i]); } write(tag, bytes); } /** * Converts string to printable and writes to der output stream. */ public void putPrintableString(String s) throws IOException { putStringType(DerValue.tag_PrintableString, s); } public void putVisibleString(String s) throws IOException { putStringType(DerValue.tag_VisibleString, s); } /** * Marshals a string which is consists of BMP (unicode) characters */ public void putBMPString(String s) throws IOException { putStringType(DerValue.tag_BMPString, s); } public void putGeneralString(String s) throws IOException { putStringType(DerValue.tag_GeneralString, s); } // /* // * T61 is an 8 bit extension to ASCII, escapes e.g. to Japanese // */ // void putT61String(String s) throws IOException // { // // XXX IMPLEMENT ME // // throw new IOException("DerOutputStream.putT61String() NYI"); // } // /* // * Universal String. // */ // void putUniversalString(String s) throws IOException // { // // XXX IMPLEMENT ME // // throw new IOException("DerOutputStream.putUniversalString() NYI"); // } /** * Marshals a string which is consists of IA5(ASCII) characters */ public void putIA5String(String s) throws IOException { putStringType(DerValue.tag_IA5String, s); } public void putUTF8String(String s) throws IOException { putStringType(DerValue.tag_UTF8String, s); } public void putStringType(byte tag, String s) throws IOException { try { CharsetEncoder encoder = ASN1CharStrConvMap.getDefault().getEncoder(tag); if (encoder == null) throw new IOException("No encoder for tag"); CharBuffer charBuffer = CharBuffer.wrap(s.toCharArray()); ByteBuffer byteBuffer = encoder.encode(charBuffer); write(tag); putLength(byteBuffer.limit()); write(byteBuffer.array(), byteBuffer.arrayOffset(), byteBuffer.limit()); } catch (CharacterCodingException e) { throw new IOException("Not a valid string type " + tag, e); } } private void put2DateBytes(byte[] buffer, int value, int offset) { int upper = value / 10; int lower = value % 10; buffer[offset] = (byte) ((byte) upper + (byte) '0'); buffer[offset + 1] = (byte) ((byte) lower + (byte) '0'); } private static Calendar GMTGregorianCalendar = null; private Calendar getGMTGregorianCalendar() { if (GMTGregorianCalendar == null) { TimeZone tz = TimeZone.getTimeZone("GMT"); GMTGregorianCalendar = new GregorianCalendar(tz); } return (Calendar) GMTGregorianCalendar.clone(); } public byte[] getDateBytes(Date d, boolean UTC) { byte[] datebytes; if (UTC) { datebytes = new byte[13]; } else { // generalized time has 4 digits for yr datebytes = new byte[15]; } Calendar cal = getGMTGregorianCalendar(); cal.setTime(d); int i = 0; if (!UTC) { put2DateBytes(datebytes, cal.get(Calendar.YEAR) / 100, i); i += 2; } put2DateBytes(datebytes, cal.get(Calendar.YEAR) % 100, i); // Calendar's MONTH is zero-based i += 2; put2DateBytes(datebytes, cal.get(Calendar.MONTH) + 1, i); i += 2; put2DateBytes(datebytes, cal.get(Calendar.DAY_OF_MONTH), i); i += 2; put2DateBytes(datebytes, cal.get(Calendar.HOUR_OF_DAY), i); i += 2; put2DateBytes(datebytes, cal.get(Calendar.MINUTE), i); i += 2; put2DateBytes(datebytes, cal.get(Calendar.SECOND), i); i += 2; // datebytes[i] = 'Z'; datebytes[i] = (byte) 'Z'; return datebytes; } /** * Marshals a DER UTC time/date value. * *

* YYMMDDhhmmss{Z|+hhmm|-hhmm} ... emits only using Zulu time and with seconds (even if seconds=0) as per IETF-PKIX * partI. */ public void putUTCTime(Date d) throws IOException { /* * Format the date. */ // This was the old code. Way too slow to be usable (stevep) // String pattern = "yyMMddHHmmss'Z'"; // SimpleDateFormat sdf = new SimpleDateFormat(pattern); // TimeZone tz = TimeZone.getTimeZone("GMT"); // sdf.setTimeZone(tz); // byte[] utc = (sdf.format(d)).getBytes(); byte[] datebytes = getDateBytes(d, true); // UTC = true /* * Write the formatted date. */ write(DerValue.tag_UtcTime); putLength(datebytes.length); write(datebytes); } /** * Marshals a DER Generalized Time/date value. * *

* YYYYMMDDhhmmss{Z|+hhmm|-hhmm} ... emits only using Zulu time and with seconds (even if seconds=0) as per * IETF-PKIX partI. */ public void putGeneralizedTime(Date d) throws IOException { /* * Format the date. */ TimeZone tz = TimeZone.getTimeZone("GMT"); // This is way too slow to be usable (stevep) String pattern = "yyyyMMddHHmmss'Z'"; SimpleDateFormat sdf = new SimpleDateFormat(pattern); sdf.setTimeZone(tz); byte[] gt = (sdf.format(d)).getBytes(); /* * Write the formatted date. */ write(DerValue.tag_GeneralizedTime); putLength(gt.length); write(gt); } /** * Put the encoding of the length in the stream. * * @param len the length of the attribute. * @exception IOException on writing errors. */ public void putLength(int len) throws IOException { if (len < 128) { write((byte) len); } else if (len < (1 << 8)) { write((byte) 0x081); write((byte) len); } else if (len < (1 << 16)) { write((byte) 0x082); write((byte) (len >> 8)); write((byte) len); } else if (len < (1 << 24)) { write((byte) 0x083); write((byte) (len >> 16)); write((byte) (len >> 8)); write((byte) len); } else { write((byte) 0x084); write((byte) (len >> 24)); write((byte) (len >> 16)); write((byte) (len >> 8)); write((byte) len); } } /** * Put the tag of the attribute in the stream. * * @param tagClass the tag class type, one of UNIVERSAL, CONTEXT, * APPLICATION or PRIVATE * @param form if true, the value is constructed, otherwise it is * primitive. * @param val the tag value */ public void putTag(byte tagClass, boolean form, byte val) { byte tag = (byte) (tagClass | val); if (form) { tag |= (byte) 0x20; } write(tag); } /** * Write the current contents of this DerOutputStream to an OutputStream. * * @exception IOException on output error. */ @Override public void derEncode(OutputStream out) throws IOException { out.write(toByteArray()); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/DerValue.java000066400000000000000000000567741412550063600270310ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.CharsetDecoder; import java.util.Arrays; import org.mozilla.jss.netscape.security.x509.AVAValueConverter; import org.mozilla.jss.netscape.security.x509.GenericValueConverter; /** * Represents a single DER-encoded value. DER encoding rules are a subset * of the "Basic" Encoding Rules (BER), but they only support a single way * ("Definite" encoding) to encode any given value. * *

* All DER-encoded data are triples {type, length, data}. This class represents such tagged values as they have * been read (or constructed), and provides structured access to the encoded data. * *

* At this time, this class supports only a subset of the types of DER data encodings which are defined. That subset is * sufficient for parsing most X.509 certificates, and working with selected additional formats (such as PKCS #10 * certificate requests, and some kinds of PKCS #7 data). * * @version 1.43 * * @author David Brownell * @author Amit Kapoor * @author Hemma Prafullchandra */ public class DerValue { /** The tag class types */ public static final byte TAG_UNIVERSAL = (byte) 0x000; public static final byte TAG_APPLICATION = (byte) 0x040; public static final byte TAG_CONTEXT = (byte) 0x080; public static final byte TAG_PRIVATE = (byte) 0x0c0; /** The DER tag of the value; one of the tag_ constants. */ public byte tag; protected DerInputBuffer buffer; /** * The DER-encoded data of the value. */ public DerInputStream data; private int length; /* * The type starts at the first byte of the encoding, and * is one of these tag_* values. That may be all the type * data that is needed. */ /* * These tags are the "universal" tags ... they mean the same * in all contexts. (Mask with 0x1f -- five bits.) */ /** Tag value indicating an ASN.1 "BOOLEAN" value. */ public final static byte tag_Boolean = 0x01; /** Tag value indicating an ASN.1 "INTEGER" value. */ public final static byte tag_Integer = 0x02; /** Tag value indicating an ASN.1 "BIT STRING" value. */ public final static byte tag_BitString = 0x03; /** Tag value indicating an ASN.1 "OCTET STRING" value. */ public final static byte tag_OctetString = 0x04; /** Tag value indicating an ASN.1 "NULL" value. */ public final static byte tag_Null = 0x05; /** Tag value indicating an ASN.1 "OBJECT IDENTIFIER" value. */ public final static byte tag_ObjectId = 0x06; /** Tag value including an ASN.1 "ENUMERATED" value */ public final static byte tag_Enumerated = 0x0A; /** Tag value including a "printable" string */ public final static byte tag_PrintableString = 0x13; public final static byte tag_VisibleString = 0x1A; /** Tag value including a "teletype" string */ public final static byte tag_T61String = 0x14; /** Tag value including an ASCII string */ public final static byte tag_IA5String = 0x16; /** Tag value indicating an ASN.1 "UTCTime" value. */ public final static byte tag_UtcTime = 0x17; /** Tag value indicating an ASN.1 "GeneralizedTime" value. */ public final static byte tag_GeneralizedTime = 0x18; /** Tag value indicating an ASN.1 "GeneralString" value. */ public final static byte tag_GeneralString = 0x1B; /** Tag value indicating an ASN.1 "BMPString" value. */ public final static byte tag_BMPString = 0x1E; /** Tag value indicating an ASN.1 "UniversalString" value. */ public final static byte tag_UniversalString = 0x1C; /** Tag value indicating an ASN.1 "UTF8String" value. (since 1998) */ public final static byte tag_UTF8String = 0x0C; public final static byte[] tags_DirectoryString = { tag_T61String , tag_PrintableString , tag_UniversalString , tag_UTF8String , tag_BMPString }; // CONSTRUCTED seq/set /** * Tag value indicating an ASN.1 * "SEQUENCE" (zero to N elements, order is significant). */ public final static byte tag_Sequence = 0x30; /** * Tag value indicating an ASN.1 * "SEQUENCE OF" (one to N elements, order is significant). */ public final static byte tag_SequenceOf = 0x30; /** * Tag value indicating an ASN.1 * "SET" (zero to N members, order does not matter). */ public final static byte tag_Set = 0x31; /** * Tag value indicating an ASN.1 * "SET OF" (one to N members, order does not matter). */ public final static byte tag_SetOf = 0x31; /* * These values are the high order bits for the other kinds of tags. */ boolean isUniversal() { return ((tag & 0x0c0) == 0x000); } boolean isApplication() { return ((tag & 0x0c0) == 0x040); } /** * Returns true iff the CONTEXT SPECIFIC bit is set in the type tag. * This is associated with the ASN.1 "DEFINED BY" syntax. */ public boolean isContextSpecific() { return ((tag & 0x0c0) == 0x080); } /** * Returns true iff the CONTEXT SPECIFIC TAG matches the passed tag. */ public boolean isContextSpecific(byte cntxtTag) { if (!isContextSpecific()) { return false; } return ((tag & 0x01f) == cntxtTag); } boolean isPrivate() { return ((tag & 0x0c0) == 0x0c0); } /** Returns true iff the CONSTRUCTED bit is set in the type tag. */ public boolean isConstructed() { return ((tag & 0x020) == 0x020); } /** * Creates a DER value from a string * using a generic way of determining the proper tag for the string. * Assumes the string is a Generic attribute value and uses * the converter for generic string values to convert to the Der Value. */ public DerValue(String value) throws IOException { AVAValueConverter genericValue = new GenericValueConverter(); DerValue val; val = genericValue.getValue(value); tag = val.tag; buffer = val.buffer; length = val.length; data = val.data; data.mark(Integer.MAX_VALUE); } /** * Creates a DerValue from a tag and some DER-encoded data. * * @param tag the DER type tag * @param data the DER-encoded data */ public DerValue(byte tag, byte[] data) { this.tag = tag; buffer = new DerInputBuffer(data.clone()); length = data.length; this.data = new DerInputStream(buffer); this.data.mark(Integer.MAX_VALUE); } /** * Creates a DerValue from a tag and some DER-encoded data. * * @param tag the DER type tag * @param data the DER-encoded data * @param offset offset of the data * @param length length of the data */ public DerValue(byte tag, byte[] data, int offset, int length) { this(tag, Arrays.copyOfRange(data, offset, offset + length)); } /* * package private */ DerValue(DerInputBuffer in) throws IOException { // NOTE: This must handle the special value used // to terminate BER indefinite encodings (tag and // length are both zero) // XXX must also parse BER-encoded constructed // values such as sequences, sets... tag = (byte) in.read(); length = DerInputStream.getLength(in); buffer = in.dup(); buffer.truncate(length); data = new DerInputStream(buffer); in.skip(length); } /** * Get an ASN.1/DER encoded datum from a buffer. The * entire buffer must hold exactly one datum, including * its tag and length. * * @param buf buffer holding a single DER-encoded datum. */ public DerValue(byte[] buf) throws IOException { init(true, new ByteArrayInputStream(buf)); } /** * Get an ASN.1/DER encoded datum from part of a buffer. * That part of the buffer must hold exactly one datum, including * its tag and length. * * @param buf the buffer * @param offset start point of the single DER-encoded dataum * @param len how many bytes are in the encoded datum */ public DerValue(byte[] buf, int offset, int len) throws IOException { init(true, new ByteArrayInputStream(buf, offset, len)); } /** * Get an ASN1/DER encoded datum from an input stream. The * stream may have additional data following the encoded datum. * * @param in the input stream holding a single DER datum, * which may be followed by additional data */ public DerValue(InputStream in) throws IOException { init(false, in); } /* * helper routine */ private void init(boolean fullyBuffered, InputStream in) throws IOException { byte[] bytes; tag = (byte) in.read(); length = DerInputStream.getLength(in); if (fullyBuffered && in.available() != length) throw new IOException("extra DER value data (constructor)"); bytes = new byte[length]; // n.b. readFully not needed in normal fullyBuffered case DataInputStream dis = new DataInputStream(in); dis.readFully(bytes); buffer = new DerInputBuffer(bytes); data = new DerInputStream(buffer); } /** * Encode an ASN1/DER encoded datum onto a DER output stream. */ public void encode(DerOutputStream out) throws IOException { out.write(tag); out.putLength(length); buffer.dump(out, length); } /** * Returns an ASN.1 BOOLEAN * * @return the boolean held in this DER value */ public boolean getBoolean() throws IOException { if (tag != tag_Boolean) { throw new IOException("DerValue.getBoolean, not a BOOLEAN " + tag); } if (length != 1) { throw new IOException("DerValue.getBoolean, invalid length " + length); } if (buffer.read() != 0) { return true; } return false; } /** * Returns an ASN.1 OBJECT IDENTIFIER. * * @return the OID held in this DER value */ public ObjectIdentifier getOID() throws IOException { if (tag != tag_ObjectId) throw new IOException("DerValue.getOID, not an OID " + tag); return new ObjectIdentifier(buffer); } /** * Returns an ASN.1 OCTET STRING * * @return the octet string held in this DER value */ public byte[] getOctetString() throws IOException { if (tag != tag_OctetString) throw new IOException( "DerValue.getOctetString, not an Octet String: " + tag); byte[] bytes = new byte[length]; int n = buffer.read(bytes); if (n != length && !(n == -1 && length == 0)) { /* We read less (or more, somehow?) than expected. * * The second condition handles a corner case: when * ByteArrayInputStream has no more data, read returns -1, even if * are asking to read 0 bytes. This seems to violate the contract * of the superclass InputStream.read() which says that if the * requested read length is 0, the return value is 0. So we have * to treat a return value of (-1) as acceptable iff the length is * zero. */ throw new IOException( "getOctetString: short read on DerValue buffer: " + "expected to read " + length + " bytes; " + "actually read " + n + " bytes."); } return bytes; } /** * Returns an ASN.1 unsigned integer value of enumerated value. * * @return the (unsigned) integer held in this DER value */ public int getEnumerated() throws IOException { if (tag != tag_Enumerated) throw new IOException("DerValue.getEnumerated, not an ENUMERATED " + tag); if (length == 0) return 0; if (length > 4 || length < 1) throw new IOException("DerValue.getEnumerated, invalid length " + length + "(must be between 1 and 4)"); int value = 0; int nextbyte = buffer.read(); if (nextbyte == -1) throw new IOException("short read on DerValue buffer"); // perform sign extension value = (byte) nextbyte; for (int i = length - 1; i > 0; --i) { nextbyte = buffer.read(); if (nextbyte == -1) throw new IOException("short read on DerValue buffer"); value = 256 * value + nextbyte; } return value; } /** * Returns an ASN.1 unsigned INTEGER value. * * @return the (unsigned) integer held in this DER value */ public BigInt getInteger() throws IOException { if (tag != tag_Integer) throw new IOException("DerValue.getInteger, not an int " + tag); return buffer.getUnsigned(data.available()); } /** * Returns an ASN.1 unsigned INTEGER value, the parameter determining * if the tag is implicit. * * @param tagImplicit if true, ignores the tag value as it is * assumed implicit. * @return the (unsigned) integer held in this DER value */ public BigInt getInteger(boolean tagImplicit) throws IOException { if (!tagImplicit) { if (tag != tag_Integer) { throw new IOException("DerValue.getInteger, not an int " + tag); } } return buffer.getUnsigned(data.available()); } /** * Returns an ASN.1 BIT STRING value. The bit string must be byte-aligned. * * @return the bit string held in this value */ public byte[] getBitString() throws IOException { if (tag != tag_BitString) throw new IOException( "DerValue.getBitString, not a bit string " + tag); return buffer.getBitString(); } /** * Returns an ASN.1 BIT STRING value that need not be byte-aligned. * * @return a BitArray representing the bit string held in this value */ public BitArray getUnalignedBitString() throws IOException { if (tag != tag_BitString) throw new IOException( "DerValue.getBitString, not a bit string " + tag); return buffer.getUnalignedBitString(); } /** * Returns the name component as a Java string, regardless of its * encoding restrictions (ASCII, T61, Printable, etc). */ public String getAsString() throws IOException { AVAValueConverter genericValue = new GenericValueConverter(); return genericValue.getAsString(this); } /** * Returns an ASN.1 BIT STRING value, with the tag assumed implicit * based on the parameter. The bit string must be byte-aligned. * * @param tagImplicit if true, the tag is assumed implicit. * @return the bit string held in this value */ public byte[] getBitString(boolean tagImplicit) throws IOException { if (!tagImplicit) { if (tag != tag_BitString) throw new IOException("DerValue.getBitString, not a bit string " + tag); } return buffer.getBitString(); } /** * Returns an ASN.1 BIT STRING value, with the tag assumed implicit * based on the parameter. The bit string need not be byte-aligned. * * @param tagImplicit if true, the tag is assumed implicit. * @return the bit string held in this value */ public BitArray getUnalignedBitString(boolean tagImplicit) throws IOException { if (!tagImplicit) { if (tag != tag_BitString) throw new IOException("DerValue.getBitString, not a bit string " + tag); } return buffer.getUnalignedBitString(); } /** * Returns an ASN.1 STRING value * * @return the printable string held in this value */ public String getPrintableString() throws IOException { if (tag != tag_PrintableString) throw new IOException( "DerValue.getPrintableString, not a string " + tag); return getASN1CharString(); } public String getDirectoryString() throws IOException { boolean tagValid = false; for (int i = 0; i < tags_DirectoryString.length; i++) { if (tag == tags_DirectoryString[i]) { tagValid = true; break; } } if (!tagValid) throw new IOException( "DerValue.getDirectoryString: invalid tag: " + tag); return getASN1CharString(); } /* * @eturns a string if the DerValue is a ASN.1 character string type and * if there is a decoder for the type. Returns null otherwise. */ public String getASN1CharString() throws IOException { try { CharsetDecoder decoder = ASN1CharStrConvMap.getDefault().getDecoder(tag); if (decoder == null) return null; ByteBuffer byteBuffer = ByteBuffer.allocate(length); data.reset(); data.getBytes(byteBuffer.array()); CharBuffer charBuffer = decoder.decode(byteBuffer); return charBuffer.toString(); } catch (CharacterCodingException e) { throw new IOException("Misformed DER value", e); } } /** * Returns an ASN.1 T61 (Teletype) STRING value * * @return the teletype string held in this value */ public String getT61String() throws IOException { if (tag != tag_T61String) throw new IOException( "DerValue.getT61String, not T61 " + tag); return getASN1CharString(); } /** * Returns an ASN.1 IA5 (ASCII) STRING value * * @return the ASCII string held in this value */ public String getIA5String() throws IOException { if (tag != tag_IA5String) throw new IOException( "DerValue.getIA5String, not IA5 " + tag); return getASN1CharString(); } public String getBMPString() throws IOException { if (tag != tag_BMPString) throw new IOException( "DerValue.getBMPString, not BMP " + tag); return getASN1CharString(); } public String getUniversalString() throws IOException { if (tag != tag_UniversalString) throw new IOException( "DerValue.getUniversalString, not UniversalString " + tag); return getASN1CharString(); } public String getUTF8String() throws IOException { if (tag != tag_UTF8String) throw new IOException( "DerValue.getUTF8String, not UTF8String " + tag); return getASN1CharString(); } /** * Returns true iff the other object is a DER value which * is bitwise equal to this one. * * @param other the object being compared with this one */ @Override public boolean equals(Object other) { if (other instanceof DerValue) return equals((DerValue) other); else return false; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((buffer == null) ? 0 : buffer.hashCode()); result = prime * result + ((data == null) ? 0 : data.hashCode()); result = prime * result + length; result = prime * result + tag; return result; } /** * Bitwise equality comparison. DER encoded values have a single * encoding, so that bitwise equality of the encoded values is an * efficient way to establish equivalence of the unencoded values. * * @param other the object being compared with this one */ public boolean equals(DerValue other) { data.reset(); other.data.reset(); if (this == other) return true; else if (tag != other.tag) { return false; } else { return buffer.equals(other.buffer); } } /** * Returns a printable representation of the value. * * @return printable representation of the value */ @Override public String toString() { try { String s = getAsString(); if (s != null) return s; if (tag == tag_Null) return "[DerValue, null]"; if (tag == tag_ObjectId) return "OID." + getOID(); // integers else return "[DerValue, tag = " + tag + ", length = " + length + "]"; } catch (IOException e) { throw new IllegalArgumentException("misformatted DER value"); } } /** * Returns a DER-encoded value, such that if it's passed to the * DerValue constructor, a value equivalent to "this" is returned. * * @return DER-encoded value, including tag and length. */ public byte[] toByteArray() throws IOException { DerOutputStream out = new DerOutputStream(); encode(out); data.reset(); return out.toByteArray(); } /** * For "set" and "sequence" types, this function may be used * to return a DER stream of the members of the set or sequence. * This operation is not supported for primitive types such as * integers or bit strings. */ public DerInputStream toDerInputStream() throws IOException { if (tag == tag_Sequence || tag == tag_Set) return new DerInputStream(buffer); throw new IOException("toDerInputStream rejects tag type " + tag); } /** * Get the length of the encoded value. */ public int length() { return length; } /** * Create the tag of the attribute. * * @param tagClass the tag class type, one of UNIVERSAL, CONTEXT, * APPLICATION or PRIVATE * @param form if true, the value is constructed, otherwise it * is primitive. * @param val the tag value */ public static byte createTag(byte tagClass, boolean form, byte val) { byte tag = (byte) (tagClass | val); if (form) { tag |= (byte) 0x20; } return (tag); } /** * Set the tag of the attribute. Commonly used to reset the * tag value used for IMPLICIT encodings. * * @param tag the tag value */ public void resetTag(byte tag) { this.tag = tag; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/ExtPrettyPrint.java000066400000000000000000002113071412550063600302700ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.io.IOException; import java.math.BigInteger; import java.security.cert.CertificateException; import java.text.DateFormat; import java.util.Enumeration; import java.util.ResourceBundle; import java.util.Vector; import org.mozilla.jss.netscape.security.extensions.AccessDescription; import org.mozilla.jss.netscape.security.extensions.AuthInfoAccessExtension; import org.mozilla.jss.netscape.security.extensions.CertificateScopeEntry; import org.mozilla.jss.netscape.security.extensions.CertificateScopeOfUseExtension; import org.mozilla.jss.netscape.security.extensions.ExtendedKeyUsageExtension; import org.mozilla.jss.netscape.security.extensions.InhibitAnyPolicyExtension; import org.mozilla.jss.netscape.security.extensions.NSCertTypeExtension; import org.mozilla.jss.netscape.security.extensions.OCSPNoCheckExtension; import org.mozilla.jss.netscape.security.extensions.PresenceServerExtension; import org.mozilla.jss.netscape.security.extensions.SubjectInfoAccessExtension; import org.mozilla.jss.netscape.security.x509.Attribute; import org.mozilla.jss.netscape.security.x509.AuthorityKeyIdentifierExtension; import org.mozilla.jss.netscape.security.x509.BasicConstraintsExtension; import org.mozilla.jss.netscape.security.x509.CPSuri; import org.mozilla.jss.netscape.security.x509.CRLDistributionPoint; import org.mozilla.jss.netscape.security.x509.CRLDistributionPointsExtension; import org.mozilla.jss.netscape.security.x509.CRLDistributionPointsExtension.Reason; import org.mozilla.jss.netscape.security.x509.CRLNumberExtension; import org.mozilla.jss.netscape.security.x509.CRLReasonExtension; import org.mozilla.jss.netscape.security.x509.CertificateIssuerExtension; import org.mozilla.jss.netscape.security.x509.CertificatePoliciesExtension; import org.mozilla.jss.netscape.security.x509.CertificatePolicyInfo; import org.mozilla.jss.netscape.security.x509.CertificatePolicyMap; import org.mozilla.jss.netscape.security.x509.DeltaCRLIndicatorExtension; import org.mozilla.jss.netscape.security.x509.DisplayText; import org.mozilla.jss.netscape.security.x509.Extension; import org.mozilla.jss.netscape.security.x509.FreshestCRLExtension; import org.mozilla.jss.netscape.security.x509.GeneralName; import org.mozilla.jss.netscape.security.x509.GeneralNameInterface; import org.mozilla.jss.netscape.security.x509.GeneralNames; import org.mozilla.jss.netscape.security.x509.HoldInstructionExtension; import org.mozilla.jss.netscape.security.x509.InvalidityDateExtension; import org.mozilla.jss.netscape.security.x509.IssuerAlternativeNameExtension; import org.mozilla.jss.netscape.security.x509.IssuingDistributionPoint; import org.mozilla.jss.netscape.security.x509.IssuingDistributionPointExtension; import org.mozilla.jss.netscape.security.x509.KeyIdentifier; import org.mozilla.jss.netscape.security.x509.KeyUsageExtension; import org.mozilla.jss.netscape.security.x509.NSCCommentExtension; import org.mozilla.jss.netscape.security.x509.NameConstraintsExtension; import org.mozilla.jss.netscape.security.x509.NoticeReference; import org.mozilla.jss.netscape.security.x509.OIDMap; import org.mozilla.jss.netscape.security.x509.PolicyConstraintsExtension; import org.mozilla.jss.netscape.security.x509.PolicyMappingsExtension; import org.mozilla.jss.netscape.security.x509.PolicyQualifierInfo; import org.mozilla.jss.netscape.security.x509.PolicyQualifiers; import org.mozilla.jss.netscape.security.x509.PrivateKeyUsageExtension; import org.mozilla.jss.netscape.security.x509.Qualifier; import org.mozilla.jss.netscape.security.x509.RDN; import org.mozilla.jss.netscape.security.x509.SerialNumber; import org.mozilla.jss.netscape.security.x509.SubjectAlternativeNameExtension; import org.mozilla.jss.netscape.security.x509.SubjectDirAttributesExtension; import org.mozilla.jss.netscape.security.x509.SubjectKeyIdentifierExtension; import org.mozilla.jss.netscape.security.x509.UserNotice; /** * This class will display the certificate content in predefined * format. * * @author Andrew Wnuk * @version $Revision$, $Date$ */ public class ExtPrettyPrint { /*========================================================== * variables *==========================================================*/ private Extension mExt = null; private ResourceBundle mResource = null; private PrettyPrintFormat pp = null; private int mIndentSize = 0; DateFormat dateFormater = null; /*========================================================== * constructors *==========================================================*/ public ExtPrettyPrint(Extension ext, int indentSize) { mExt = ext; mResource = ResourceBundle.getBundle(PrettyPrintResources.class.getName()); mIndentSize = indentSize; pp = new PrettyPrintFormat(":"); } /*========================================================== * public methods *==========================================================*/ /** * This method return string representation of the certificate * in predefined format using specified client local. I18N Support. * * @return string representation of the certificate */ @Override public String toString() { StringBuffer sb = new StringBuffer(); //check if the extension is known if (mExt instanceof KeyUsageExtension) { return getKeyUsage(); } if (mExt instanceof NSCertTypeExtension) { return getCertType(); } if (mExt instanceof AuthorityKeyIdentifierExtension) { return getAuthorityKeyIdentifier(); } if (mExt instanceof SubjectKeyIdentifierExtension) { return getSubjectKeyIdentifier(); } if (mExt instanceof CRLReasonExtension) { return getCRLReasonExtension(); } if (mExt instanceof BasicConstraintsExtension) { return getBasicConstraintsExtension(); } if (mExt instanceof NSCCommentExtension) { return getNSCCommentExtension(); } if (mExt instanceof NameConstraintsExtension) { return getNameConstraintsExtension(); } if (mExt instanceof CRLNumberExtension) { return getCRLNumberExtension(); } if (mExt instanceof DeltaCRLIndicatorExtension) { return getDeltaCRLIndicatorExtension(); } if (mExt instanceof IssuerAlternativeNameExtension) { return getIssuerAlternativeNameExtension(); } if (mExt instanceof SubjectAlternativeNameExtension) { return getSubjectAlternativeNameExtension(); } if (mExt instanceof FreshestCRLExtension) { return getFreshestCRLExtension(); } if (mExt instanceof CRLDistributionPointsExtension) { return getCRLDistributionPointsExtension(); } if (mExt instanceof IssuingDistributionPointExtension) { return getIssuingDistributionPointExtension(); } if (mExt instanceof ExtendedKeyUsageExtension) { return getExtendedKeyUsageExtension(); } if (mExt instanceof AuthInfoAccessExtension) { return getAuthInfoAccessExtension(); } if (mExt instanceof SubjectInfoAccessExtension) { return getSubjectInfoAccessExtension(); } if (mExt instanceof OCSPNoCheckExtension) { return getOCSPNoCheckExtension(); } if (mExt instanceof PrivateKeyUsageExtension) { return getPrivateKeyUsageExtension(); } if (mExt instanceof InvalidityDateExtension) { return getInvalidityDateExtension(); } if (mExt instanceof CertificateIssuerExtension) { return getCertificateIssuerExtension(); } if (mExt instanceof HoldInstructionExtension) { return getHoldInstructionExtension(); } if (mExt instanceof PolicyConstraintsExtension) { return getPolicyConstraintsExtension(); } if (mExt instanceof PolicyMappingsExtension) { return getPolicyMappingsExtension(); } if (mExt instanceof SubjectDirAttributesExtension) { return getSubjectDirAttributesExtension(); } if (mExt instanceof CertificateScopeOfUseExtension) { return getCertificateScopeOfUseExtension(); } if (mExt instanceof PresenceServerExtension) { return getPresenceServerExtension(); } if (mExt instanceof InhibitAnyPolicyExtension) { return getInhibitAnyPolicyExtension(); } if (mExt instanceof CertificatePoliciesExtension) { return getCertificatePoliciesExtension(); } //unknown cert extension String extName = OIDMap.getName(mExt.getExtensionId()); if (extName == null) sb.append(pp.indent(mIndentSize) + mResource.getString( PrettyPrintResources.TOKEN_IDENTIFIER) + mExt.getExtensionId().toString() + "\n"); else sb.append(pp.indent(mIndentSize) + mResource.getString( PrettyPrintResources.TOKEN_IDENTIFIER) + " " + extName + " - " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_CRITICAL)); if (mExt.isCritical()) { sb.append(mResource.getString( PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString( PrettyPrintResources.TOKEN_NO) + "\n"); } sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_VALUE) + "\n"); sb.append(pp.toHexString(mExt.getExtensionValue(), mIndentSize + 8, 16)); return sb.toString(); } /*========================================================== * Private methods *==========================================================*/ private String getNSCCommentExtension() { StringBuffer sb = new StringBuffer(); sb.append(pp.indent(mIndentSize) + mResource.getString( PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_NSC_COMMENT) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_CRITICAL)); if (mExt.isCritical()) { sb.append(mResource.getString( PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString( PrettyPrintResources.TOKEN_NO) + "\n"); } sb.append(pp.indent(mIndentSize + 4) + ((NSCCommentExtension) mExt).toPrint(mIndentSize) + "\n"); return sb.toString(); } private String getNameConstraintsExtension() { StringBuffer sb = new StringBuffer(); sb.append(pp.indent(mIndentSize) + mResource.getString( PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_NAME_CONSTRAINTS) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_CRITICAL)); if (mExt.isCritical()) { sb.append(mResource.getString( PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString( PrettyPrintResources.TOKEN_NO) + "\n"); } sb.append(pp.indent(mIndentSize + 4) + ((NameConstraintsExtension) mExt).toPrint(mIndentSize + 4)); return sb.toString(); } private String getOCSPNoCheckExtension() { StringBuffer sb = new StringBuffer(); sb.append(pp.indent(mIndentSize) + mResource.getString( PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_OCSP_NOCHECK) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_CRITICAL)); if (mExt.isCritical()) { sb.append(mResource.getString( PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString( PrettyPrintResources.TOKEN_NO) + "\n"); } return sb.toString(); } private String getSubjectInfoAccessExtension() { StringBuffer sb = new StringBuffer(); sb.append(pp.indent(mIndentSize) + mResource.getString( PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_SIA) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_CRITICAL)); if (mExt.isCritical()) { sb.append(mResource.getString( PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString( PrettyPrintResources.TOKEN_NO) + "\n"); } sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_ACCESS_DESC) + "\n"); SubjectInfoAccessExtension aia = (SubjectInfoAccessExtension) mExt; for (int i = 0; i < aia.numberOfAccessDescription(); i++) { AccessDescription ad = aia.getAccessDescription(i); ObjectIdentifier method = ad.getMethod(); if (method.equals(SubjectInfoAccessExtension.METHOD_OCSP)) { sb.append(pp.indent(mIndentSize + 8) + "Method #" + i + ": " + "ocsp" + "\n"); } else { sb.append(pp.indent(mIndentSize + 8) + "Method #" + i + ": " + method.toString() + "\n"); } sb.append(pp.indent(mIndentSize + 8) + "Location #" + i + ": " + ad.getLocation().toString() + "\n"); } return sb.toString(); } private String getAuthInfoAccessExtension() { StringBuffer sb = new StringBuffer(); sb.append(pp.indent(mIndentSize) + mResource.getString( PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_AIA) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_CRITICAL)); if (mExt.isCritical()) { sb.append(mResource.getString( PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString( PrettyPrintResources.TOKEN_NO) + "\n"); } sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_ACCESS_DESC) + "\n"); AuthInfoAccessExtension aia = (AuthInfoAccessExtension) mExt; for (int i = 0; i < aia.numberOfAccessDescription(); i++) { AccessDescription ad = aia.getAccessDescription(i); ObjectIdentifier method = ad.getMethod(); if (method.equals(AuthInfoAccessExtension.METHOD_OCSP)) { sb.append(pp.indent(mIndentSize + 8) + "Method #" + i + ": " + "ocsp" + "\n"); } else { sb.append(pp.indent(mIndentSize + 8) + "Method #" + i + ": " + method.toString() + "\n"); } sb.append(pp.indent(mIndentSize + 8) + "Location #" + i + ": " + ad.getLocation().toString() + "\n"); } return sb.toString(); } private String getPresenceServerExtension() { StringBuffer sb = new StringBuffer(); sb.append(pp.indent(mIndentSize) + mResource.getString( PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_PRESENCE_SERVER) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_CRITICAL)); if (mExt.isCritical()) { sb.append(mResource.getString( PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString( PrettyPrintResources.TOKEN_NO) + "\n"); } PresenceServerExtension pse = (PresenceServerExtension) mExt; sb.append(pp.indent(mIndentSize + 4) + "Version : " + pse.getVersion() + "\n"); sb.append(pp.indent(mIndentSize + 4) + "Street Address : " + pse.getStreetAddress() + "\n"); sb.append(pp.indent(mIndentSize + 4) + "Telephone Number : " + pse.getTelephoneNumber() + "\n"); sb.append(pp.indent(mIndentSize + 4) + "RFC822 Name : " + pse.getRFC822() + "\n"); sb.append(pp.indent(mIndentSize + 4) + "ID : " + pse.getID() + "\n"); sb.append(pp.indent(mIndentSize + 4) + "Host Name : " + pse.getHostName() + "\n"); sb.append(pp.indent(mIndentSize + 4) + "Port Number : " + pse.getPortNumber() + "\n"); sb.append(pp.indent(mIndentSize + 4) + "Max Users : " + pse.getMaxUsers() + "\n"); sb.append(pp.indent(mIndentSize + 4) + "Service Level : " + pse.getServiceLevel() + "\n"); return sb.toString(); } private String getPrivateKeyUsageExtension() { StringBuffer sb = new StringBuffer(); sb.append(pp.indent(mIndentSize) + mResource.getString( PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_PRIVATE_KEY_USAGE) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_CRITICAL)); if (mExt.isCritical()) { sb.append(mResource.getString( PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString( PrettyPrintResources.TOKEN_NO) + "\n"); } PrivateKeyUsageExtension usage = (PrivateKeyUsageExtension) mExt; sb.append(pp.indent(mIndentSize + 4) + "Validity:\n"); if (dateFormater == null) { dateFormater = DateFormat.getDateInstance(DateFormat.FULL); } String notBefore = dateFormater.format(usage.getNotBefore()); String notAfter = dateFormater.format(usage.getNotAfter()); sb.append(pp.indent(mIndentSize + 8) + "Not Before: " + notBefore + "\n"); sb.append(pp.indent(mIndentSize + 8) + "Not After: " + notAfter + "\n"); return sb.toString(); } private String getExtendedKeyUsageExtension() { StringBuffer sb = new StringBuffer(); sb.append(pp.indent(mIndentSize) + mResource.getString( PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_EXTENDED_KEY_USAGE) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_CRITICAL)); if (mExt.isCritical()) { sb.append(mResource.getString( PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString( PrettyPrintResources.TOKEN_NO) + "\n"); } sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_EXTENDED_KEY_USAGE) + "\n"); ExtendedKeyUsageExtension usage = (ExtendedKeyUsageExtension) mExt; Enumeration e = usage.getOIDs(); if (e != null) { while (e.hasMoreElements()) { ObjectIdentifier oid = e.nextElement(); if (oid.equals(ExtendedKeyUsageExtension.OID_OCSP_SIGNING)) { sb.append(pp.indent(mIndentSize + 8) + "OCSPSigning" + "\n"); } else { sb.append(pp.indent(mIndentSize + 8) + oid.toString() + "\n"); } } } return sb.toString(); } /** * String Representation of KeyUsageExtension */ private String getKeyUsage() { StringBuffer sb = new StringBuffer(); try { sb.append(pp.indent(mIndentSize) + mResource.getString( PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_KEY_USAGE) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_CRITICAL)); if (mExt.isCritical()) { sb.append(mResource.getString( PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString( PrettyPrintResources.TOKEN_NO) + "\n"); } sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_KEY_USAGE) + "\n"); KeyUsageExtension usage = (KeyUsageExtension) mExt; if (((Boolean) usage.get(KeyUsageExtension.DIGITAL_SIGNATURE)).booleanValue()) { sb.append(pp.indent(mIndentSize + 8) + mResource.getString(KeyUsageExtension.DIGITAL_SIGNATURE) + "\n"); } if (((Boolean) usage.get(KeyUsageExtension.NON_REPUDIATION)).booleanValue()) { sb.append(pp.indent(mIndentSize + 8) + mResource.getString(KeyUsageExtension.NON_REPUDIATION) + "\n"); } if (((Boolean) usage.get(KeyUsageExtension.KEY_ENCIPHERMENT)).booleanValue()) { sb.append(pp.indent(mIndentSize + 8) + mResource.getString(KeyUsageExtension.KEY_ENCIPHERMENT) + "\n"); } if (((Boolean) usage.get(KeyUsageExtension.DATA_ENCIPHERMENT)).booleanValue()) { sb.append(pp.indent(mIndentSize + 8) + mResource.getString(KeyUsageExtension.DATA_ENCIPHERMENT) + "\n"); } if (((Boolean) usage.get(KeyUsageExtension.KEY_AGREEMENT)).booleanValue()) { sb.append(pp.indent(mIndentSize + 8) + mResource.getString(KeyUsageExtension.KEY_AGREEMENT) + "\n"); } if (((Boolean) usage.get(KeyUsageExtension.KEY_CERTSIGN)).booleanValue()) { sb.append(pp.indent(mIndentSize + 8) + mResource.getString(KeyUsageExtension.KEY_CERTSIGN) + "\n"); } if (((Boolean) usage.get(KeyUsageExtension.CRL_SIGN)).booleanValue()) { sb.append(pp.indent(mIndentSize + 8) + mResource.getString(KeyUsageExtension.CRL_SIGN) + "\n"); } if (((Boolean) usage.get(KeyUsageExtension.ENCIPHER_ONLY)).booleanValue()) { sb.append(pp.indent(mIndentSize + 8) + mResource.getString(KeyUsageExtension.ENCIPHER_ONLY) + "\n"); } if (((Boolean) usage.get(KeyUsageExtension.DECIPHER_ONLY)).booleanValue()) { sb.append(pp.indent(mIndentSize + 8) + mResource.getString(KeyUsageExtension.DECIPHER_ONLY) + "\n"); } return sb.toString(); } catch (IOException e) { e.printStackTrace(); return sb.toString(); } } /** * String Representation of NSCertTypeExtension */ private String getCertType() { StringBuffer sb = new StringBuffer(); try { sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_CERT_TYPE) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL)); if (mExt.isCritical()) { sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n"); } sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CERT_USAGE) + "\n"); NSCertTypeExtension type = (NSCertTypeExtension) mExt; if (((Boolean) type.get(NSCertTypeExtension.SSL_CLIENT)).booleanValue()) { sb.append(pp.indent(mIndentSize + 8) + mResource.getString(NSCertTypeExtension.SSL_CLIENT) + "\n"); } if (((Boolean) type.get(NSCertTypeExtension.SSL_SERVER)).booleanValue()) { sb.append(pp.indent(mIndentSize + 8) + mResource.getString(NSCertTypeExtension.SSL_SERVER) + "\n"); } if (((Boolean) type.get(NSCertTypeExtension.EMAIL)).booleanValue()) { sb.append(pp.indent(mIndentSize + 8) + mResource.getString(NSCertTypeExtension.EMAIL) + "\n"); } if (((Boolean) type.get(NSCertTypeExtension.OBJECT_SIGNING)).booleanValue()) { sb.append(pp.indent(mIndentSize + 8) + mResource.getString(NSCertTypeExtension.OBJECT_SIGNING) + "\n"); } if (((Boolean) type.get(NSCertTypeExtension.SSL_CA)).booleanValue()) { sb.append(pp.indent(mIndentSize + 8) + mResource.getString(NSCertTypeExtension.SSL_CA) + "\n"); } if (((Boolean) type.get(NSCertTypeExtension.EMAIL_CA)).booleanValue()) { sb.append(pp.indent(mIndentSize + 8) + mResource.getString(NSCertTypeExtension.EMAIL_CA) + "\n"); } if (((Boolean) type.get(NSCertTypeExtension.OBJECT_SIGNING_CA)).booleanValue()) { sb.append(pp.indent(mIndentSize + 8) + mResource.getString(NSCertTypeExtension.OBJECT_SIGNING_CA) + "\n"); } return sb.toString(); } catch (CertificateException e) { e.printStackTrace(); return ""; } } /** * String Representation of SubjectKeyIdentifierExtension */ private String getSubjectKeyIdentifier() { StringBuffer sb = new StringBuffer(); try { sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_SKI) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL)); if (mExt.isCritical()) { sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n"); } SubjectKeyIdentifierExtension id = (SubjectKeyIdentifierExtension) mExt; KeyIdentifier keyId = (KeyIdentifier) id.get(SubjectKeyIdentifierExtension.KEY_ID); if (keyId != null) { sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_KEY_ID) + "\n"); sb.append(pp.toHexString(keyId.getIdentifier(), 24, 16)); } return sb.toString(); } catch (IOException e) { e.printStackTrace(); return ""; } } /** * String Representation of AuthorityKeyIdentifierExtension */ private String getAuthorityKeyIdentifier() { StringBuffer sb = new StringBuffer(); try { sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_AKI) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL)); if (mExt.isCritical()) { sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n"); } AuthorityKeyIdentifierExtension id = (AuthorityKeyIdentifierExtension) mExt; KeyIdentifier keyId = (KeyIdentifier) id.get(AuthorityKeyIdentifierExtension.KEY_ID); if (keyId != null) { sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_KEY_ID) + "\n"); sb.append(pp.toHexString(keyId.getIdentifier(), mIndentSize + 8, 16)); // sb.append(pp.toHexString(keyId.getIdentifier(),24,16)); } GeneralNames authNames = (GeneralNames) id.get(AuthorityKeyIdentifierExtension.AUTH_NAME); if (authNames != null) { for (int i = 0; i < authNames.size(); i++) { GeneralName authName = (GeneralName) authNames.elementAt(i); if (authName != null) { sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_AUTH_NAME) + authName.toString() + "\n"); } } } SerialNumber serial = (SerialNumber) id.get(AuthorityKeyIdentifierExtension.SERIAL_NUMBER); if (serial != null) { sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_SERIAL) + "0x" + serial.getNumber().toBigInteger().toString(16).toUpperCase() + "\n"); } return sb.toString(); } catch (IOException e) { e.printStackTrace(); return ""; } } /** * String Representation of CRLReasonExtension */ private String getCRLReasonExtension() { StringBuffer sb = new StringBuffer(); try { sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_REVOCATION_REASON) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL)); CRLReasonExtension ext = (CRLReasonExtension) mExt; if (mExt.isCritical()) { sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n"); } sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_REASON) + ext.getReason().toString() + "\n"); return sb.toString(); } catch (Exception e) { return ""; } } /** * String Representation of InhibitAnyPolicyExtension */ private String getInhibitAnyPolicyExtension() { StringBuffer sb = new StringBuffer(); sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString( PrettyPrintResources.TOKEN_INHIBIT_ANY_POLICY_EXT) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL)); InhibitAnyPolicyExtension ext = (InhibitAnyPolicyExtension) mExt; if (mExt.isCritical()) sb.append(mResource.getString( PrettyPrintResources.TOKEN_YES) + "\n"); else sb.append(mResource.getString( PrettyPrintResources.TOKEN_NO) + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_SKIP_CERTS)); BigInt num = ext.getSkipCerts(); sb.append("" + num.toInt() + "\n"); return sb.toString(); } /** * String Representation of BasicConstraintsExtension */ private String getBasicConstraintsExtension() { StringBuffer sb = new StringBuffer(); try { sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_BASIC_CONSTRAINTS) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL)); BasicConstraintsExtension ext = (BasicConstraintsExtension) mExt; if (mExt.isCritical()) { sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n"); } sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_IS_CA)); boolean isCA = ((Boolean) ext.get(BasicConstraintsExtension.IS_CA)).booleanValue(); if (isCA) { sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n"); } Integer pathLength = (Integer) ext.get(BasicConstraintsExtension.PATH_LEN); if (pathLength != null) { if (pathLength.longValue() >= 0) { sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_PATH_LEN) + pathLength.toString() + "\n"); } else if (pathLength.longValue() == -1 || pathLength.longValue() == -2) { sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_PATH_LEN) + mResource.getString(PrettyPrintResources.TOKEN_PATH_LEN_UNLIMITED) + "\n"); } else { sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_PATH_LEN) + mResource.getString(PrettyPrintResources.TOKEN_PATH_LEN_INVALID) + " (" + pathLength.toString() + ")\n"); } } return sb.toString(); } catch (IOException e) { e.printStackTrace(); return ""; } } /** * String Representation of CRLNumberExtension */ private String getCRLNumberExtension() { StringBuffer sb = new StringBuffer(); try { sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_CRL_NUMBER) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL)); CRLNumberExtension ext = (CRLNumberExtension) mExt; if (mExt.isCritical()) { sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n"); } BigInteger crlNumber = (BigInteger) ext.get(CRLNumberExtension.NUMBER); if (crlNumber != null) { sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_NUMBER) + crlNumber.toString() + "\n"); } return sb.toString(); } catch (IOException e) { e.printStackTrace(); return ""; } } /** * String Representation of DeltaCRLIndicatorExtension */ private String getDeltaCRLIndicatorExtension() { StringBuffer sb = new StringBuffer(); try { sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_DELTA_CRL_INDICATOR) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL)); DeltaCRLIndicatorExtension ext = (DeltaCRLIndicatorExtension) mExt; if (mExt.isCritical()) { sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n"); } BigInteger crlNumber = (BigInteger) ext.get(DeltaCRLIndicatorExtension.NUMBER); if (crlNumber != null) { sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_BASE_CRL_NUMBER) + crlNumber.toString() + "\n"); } return sb.toString(); } catch (IOException e) { e.printStackTrace(); return ""; } } /** * String Representation of IssuerAlternativeName Extension */ private String getIssuerAlternativeNameExtension() { StringBuffer sb = new StringBuffer(); try { sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_ISSUER_ALT_NAME) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL)); IssuerAlternativeNameExtension ext = (IssuerAlternativeNameExtension) mExt; if (mExt.isCritical()) { sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n"); } GeneralNames issuerNames = (GeneralNames) ext.get(IssuerAlternativeNameExtension.ISSUER_NAME); if (issuerNames != null) { sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_ISSUER_NAMES) + "\n"); for (int i = 0; i < issuerNames.size(); i++) { GeneralName issuerName = (GeneralName) issuerNames.elementAt(i); if (issuerName != null) { String nameType = ""; if (issuerName.getType() == GeneralNameInterface.NAME_DIRECTORY) nameType = "DirectoryName: "; sb.append(pp.indent(mIndentSize + 8) + nameType + issuerName.toString() + "\n"); } } } return sb.toString(); } catch (IOException e) { return ""; } } /** * String Representation of SubjectAlternativeName Extension */ private String getSubjectAlternativeNameExtension() { StringBuffer sb = new StringBuffer(); try { sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_SUBJECT_ALT_NAME) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL)); SubjectAlternativeNameExtension ext = (SubjectAlternativeNameExtension) mExt; if (mExt.isCritical()) { sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n"); } GeneralNames subjectNames = (GeneralNames) ext.get(SubjectAlternativeNameExtension.SUBJECT_NAME); sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_VALUE) + "\n"); for (int i = 0; i < subjectNames.size(); i++) { GeneralName subjectName = (GeneralName) subjectNames.elementAt(i); if (subjectName != null) { String nameType = ""; if (subjectName.getType() == GeneralNameInterface.NAME_DIRECTORY) nameType = "DirectoryName: "; sb.append(pp.indent(mIndentSize + 8) + nameType + subjectName.toString() + "\n"); } } return sb.toString(); } catch (IOException e) { e.printStackTrace(); return ""; } } /** * String Representation of CertificateScopeOfUse Extension */ private String getCertificateScopeOfUseExtension() { StringBuffer sb = new StringBuffer(); sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_CERT_SCOPE_OF_USE) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL)); CertificateScopeOfUseExtension ext = (CertificateScopeOfUseExtension) mExt; if (mExt.isCritical()) { sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n"); } Vector entries = ext.getCertificateScopeEntries(); if (entries != null) { sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_SCOPE_OF_USE) + "\n"); for (int i = 0; i < entries.size(); i++) { CertificateScopeEntry se = entries.elementAt(i); GeneralName gn = se.getGeneralName(); if (gn != null) { String nameType = ""; if (gn.getType() == GeneralNameInterface.NAME_DIRECTORY) nameType = "DirectoryName: "; sb.append(pp.indent(mIndentSize + 8) + nameType + gn.toString() + "\n"); } BigInt port = se.getPort(); if (port != null) { sb.append(pp.indent(mIndentSize + 8) + PrettyPrintResources.TOKEN_PORT + port.toBigInteger().toString() + "\n"); } } } return sb.toString(); } /** * String Representation of FreshestCRLExtension */ private String getFreshestCRLExtension() { StringBuffer sb = new StringBuffer(); // // Generic stuff: name, OID, criticality // sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString( PrettyPrintResources.TOKEN_FRESHEST_CRL_EXT) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL)); if (mExt.isCritical()) { sb.append(mResource.getString( PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString( PrettyPrintResources.TOKEN_NO) + "\n"); } // // Now the CRLDP-specific stuff // FreshestCRLExtension ext = (FreshestCRLExtension) mExt; int numPoints = ext.getNumPoints(); sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_CRLDP_NUMPOINTS) + numPoints + "\n"); for (int i = 0; i < numPoints; i++) { // // print one individual CRL distribution point // int idt; idt = mIndentSize + 4; // reset each time through loop boolean isEmpty = true; sb.append(pp.indent(idt) + mResource.getString(PrettyPrintResources.TOKEN_CRLDP_POINTN) + i + "\n"); CRLDistributionPoint pt = ext.getPointAt(i); idt += 4; // further indent rest of information if (pt.getFullName() != null) { isEmpty = false; sb.append(pp.indent(idt) + mResource.getString(PrettyPrintResources.TOKEN_CRLDP_DISTPOINT) + pt.getFullName() + "\n"); } if (pt.getRelativeName() != null) { isEmpty = false; sb.append(pp.indent(idt) + mResource.getString(PrettyPrintResources.TOKEN_CRLDP_DISTPOINT) + pt.getRelativeName() + "\n"); } if (pt.getReasons() != null) { isEmpty = false; byte[] reasonBits = pt.getReasons().toByteArray(); String reasonList = reasonBitsToReasonList(reasonBits); sb.append(pp.indent(idt) + mResource.getString(PrettyPrintResources.TOKEN_CRLDP_REASONS) + reasonList + "\n"); } if (pt.getCRLIssuer() != null) { isEmpty = false; sb.append(pp.indent(idt) + mResource.getString(PrettyPrintResources.TOKEN_CRLDP_CRLISSUER) + pt.getCRLIssuer() + "\n"); } if (isEmpty) { sb.append(pp.indent(idt) + "empty\n"); } } return sb.toString(); } /** * String Representation of CRLDistributionPointsExtension */ private String getCRLDistributionPointsExtension() { StringBuffer sb = new StringBuffer(); // // Generic stuff: name, OID, criticality // sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString( PrettyPrintResources.TOKEN_CRL_DP_EXT) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL)); if (mExt.isCritical()) { sb.append(mResource.getString( PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString( PrettyPrintResources.TOKEN_NO) + "\n"); } // // Now the CRLDP-specific stuff // CRLDistributionPointsExtension ext = (CRLDistributionPointsExtension) mExt; int numPoints = ext.getNumPoints(); sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_CRLDP_NUMPOINTS) + numPoints + "\n"); for (int i = 0; i < numPoints; i++) { // // print one individual CRL distribution point // int idt; idt = mIndentSize + 4; // reset each time through loop boolean isEmpty = true; sb.append(pp.indent(idt) + mResource.getString(PrettyPrintResources.TOKEN_CRLDP_POINTN) + i + "\n"); CRLDistributionPoint pt = ext.getPointAt(i); idt += 4; // further indent rest of information if (pt.getFullName() != null) { isEmpty = false; sb.append(pp.indent(idt) + mResource.getString(PrettyPrintResources.TOKEN_CRLDP_DISTPOINT) + pt.getFullName() + "\n"); } if (pt.getRelativeName() != null) { isEmpty = false; sb.append(pp.indent(idt) + mResource.getString(PrettyPrintResources.TOKEN_CRLDP_DISTPOINT) + pt.getRelativeName() + "\n"); } if (pt.getReasons() != null) { isEmpty = false; byte[] reasonBits = pt.getReasons().toByteArray(); String reasonList = reasonBitsToReasonList(reasonBits); sb.append(pp.indent(idt) + mResource.getString(PrettyPrintResources.TOKEN_CRLDP_REASONS) + reasonList + "\n"); } if (pt.getCRLIssuer() != null) { isEmpty = false; sb.append(pp.indent(idt) + mResource.getString(PrettyPrintResources.TOKEN_CRLDP_CRLISSUER) + pt.getCRLIssuer() + "\n"); } if (isEmpty) { sb.append(pp.indent(idt) + "empty\n"); } } return sb.toString(); } private static String reasonBitsToReasonList(byte[] reasonBits) { Reason[] reasons = Reason.bitArrayToReasonArray(reasonBits); if (reasons.length == 0) { return ""; } else { StringBuffer buf = new StringBuffer(); buf.append(reasons[0].getName()); for (int i = 1; i < reasons.length; i++) { buf.append(", "); buf.append(reasons[i].getName()); } return buf.toString(); } } /** * String Representation of IssuerAlternativeName Extension */ private String getIssuingDistributionPointExtension() { StringBuffer sb = new StringBuffer(); sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_ISSUING_DIST_POINT) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL)); if (mExt.isCritical()) { sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n"); } IssuingDistributionPointExtension ext = (IssuingDistributionPointExtension) mExt; IssuingDistributionPoint issuingDistributionPoint = ext.getIssuingDistributionPoint(); if (issuingDistributionPoint != null) { GeneralNames fullNames = issuingDistributionPoint.getFullName(); RDN relativeName = issuingDistributionPoint.getRelativeName(); if (fullNames != null || relativeName != null) { sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_DIST_POINT_NAME) + "\n"); if (fullNames != null) { sb.append(pp.indent(mIndentSize + 8) + mResource.getString(PrettyPrintResources.TOKEN_FULL_NAME) + "\n"); for (int i = 0; i < fullNames.size(); i++) { GeneralName fullName = (GeneralName) fullNames.elementAt(i); if (fullName != null) { sb.append(pp.indent(mIndentSize + 12) + fullName.toString() + "\n"); } } } if (relativeName != null) { sb.append(pp.indent(mIndentSize + 8) + mResource.getString(PrettyPrintResources.TOKEN_RELATIVE_NAME) + relativeName.toString() + "\n"); } } sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_ONLY_USER_CERTS)); if (issuingDistributionPoint.getOnlyContainsUserCerts()) { sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n"); } sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_ONLY_CA_CERTS)); if (issuingDistributionPoint.getOnlyContainsCACerts()) { sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n"); } BitArray onlySomeReasons = issuingDistributionPoint.getOnlySomeReasons(); if (onlySomeReasons != null) { sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_ONLY_SOME_REASONS)); sb.append("0x" + pp.toHexString(onlySomeReasons.toByteArray())); } sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_INDIRECT_CRL)); if (issuingDistributionPoint.getIndirectCRL()) { sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n"); } } return sb.toString(); } /** * String Representation of InvalidityDateExtension */ private String getInvalidityDateExtension() { StringBuffer sb = new StringBuffer(); sb.append(pp.indent(mIndentSize) + mResource.getString( PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_INVALIDITY_DATE) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_CRITICAL)); InvalidityDateExtension ext = (InvalidityDateExtension) mExt; if (mExt.isCritical()) { sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n"); } sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_DATE_OF_INVALIDITY) + ext.getInvalidityDate().toString() + "\n"); return sb.toString(); } /** * String Representation of CertificateIssuerExtension */ private String getCertificateIssuerExtension() { StringBuffer sb = new StringBuffer(); try { sb.append(pp.indent(mIndentSize) + mResource.getString( PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_CERTIFICATE_ISSUER) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_CRITICAL)); CertificateIssuerExtension ext = (CertificateIssuerExtension) mExt; if (mExt.isCritical()) { sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n"); } GeneralNames issuerNames = (GeneralNames) ext.get( CertificateIssuerExtension.CERTIFICATE_ISSUER); if (issuerNames != null) { sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_ISSUER_NAMES) + "\n"); for (int i = 0; i < issuerNames.size(); i++) { GeneralName issuerName = (GeneralName) issuerNames.elementAt(i); if (issuerName != null) { String nameType = ""; if (issuerName.getType() == GeneralNameInterface.NAME_DIRECTORY) nameType = "DirectoryName: "; sb.append(pp.indent(mIndentSize + 8) + nameType + issuerName.toString() + "\n"); } } } return sb.toString(); } catch (IOException e) { e.printStackTrace(); return ""; } } /** * String Representation of HoldInstructionExtension */ private String getHoldInstructionExtension() { StringBuffer sb = new StringBuffer(); sb.append(pp.indent(mIndentSize) + mResource.getString( PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_HOLD_INSTRUCTION) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_CRITICAL)); HoldInstructionExtension ext = (HoldInstructionExtension) mExt; if (mExt.isCritical()) { sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n"); } sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_HOLD_INSTRUCTION_CODE) + ext.getHoldInstructionCodeDescription() + "\n"); return sb.toString(); } /** * String Representation of PolicyConstraintsExtension */ private String getPolicyConstraintsExtension() { StringBuffer sb = new StringBuffer(); sb.append(pp.indent(mIndentSize) + mResource.getString( PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append( mResource.getString( PrettyPrintResources.TOKEN_POLICY_CONSTRAINTS) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_CRITICAL)); if (mExt.isCritical()) { sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n"); } PolicyConstraintsExtension ext = (PolicyConstraintsExtension) mExt; int require = ext.getRequireExplicitMapping(); int inhibit = ext.getInhibitPolicyMapping(); sb.append( pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_REQUIRE_EXPLICIT_POLICY) + ((require == -1) ? mResource.getString(PrettyPrintResources.TOKEN_NOT_SET) : String.valueOf(require)) + "\n"); sb.append( pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_INHIBIT_POLICY_MAPPING) + ((inhibit == -1) ? mResource.getString(PrettyPrintResources.TOKEN_NOT_SET) : String.valueOf(inhibit)) + "\n"); return sb.toString(); } /** * String Representation of PolicyMappingsExtension */ private String getPolicyMappingsExtension() { StringBuffer sb = new StringBuffer(); sb.append(pp.indent(mIndentSize) + mResource.getString( PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_POLICY_MAPPINGS) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_CRITICAL)); if (mExt.isCritical()) { sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n"); } PolicyMappingsExtension ext = (PolicyMappingsExtension) mExt; Enumeration maps = ext.getMappings(); sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_MAPPINGS)); if (maps == null || !maps.hasMoreElements()) { sb.append( mResource.getString(PrettyPrintResources.TOKEN_NONE) + "\n"); } else { sb.append("\n"); for (int i = 0; maps.hasMoreElements(); i++) { sb.append(pp.indent(mIndentSize + 8) + mResource.getString( PrettyPrintResources.TOKEN_MAP) + i + ":" + "\n"); CertificatePolicyMap m = maps.nextElement(); sb.append(pp.indent(mIndentSize + 12) + mResource.getString( PrettyPrintResources.TOKEN_ISSUER_DOMAIN_POLICY) + m.getIssuerIdentifier().getIdentifier().toString() + "\n"); sb.append(pp.indent(mIndentSize + 12) + mResource.getString( PrettyPrintResources.TOKEN_SUBJECT_DOMAIN_POLICY) + m.getSubjectIdentifier().getIdentifier().toString() + "\n"); } } return sb.toString(); } /** * String Representation of SubjectDirAttributesExtension */ private String getSubjectDirAttributesExtension() { StringBuffer sb = new StringBuffer(); try { sb.append(pp.indent(mIndentSize) + mResource.getString( PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_SUBJECT_DIR_ATTR) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL)); if (mExt.isCritical()) { sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n"); } SubjectDirAttributesExtension ext = (SubjectDirAttributesExtension) mExt; sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_ATTRIBUTES)); Enumeration attrs = ext.getAttributesList(); if (attrs == null || !attrs.hasMoreElements()) { sb.append( mResource.getString(PrettyPrintResources.TOKEN_NONE) + "\n"); } else { sb.append("\n"); for (int j = 0; attrs.hasMoreElements(); j++) { Attribute attr = attrs.nextElement(); sb.append(pp.indent(mIndentSize + 8) + mResource.getString( PrettyPrintResources.TOKEN_ATTRIBUTE) + j + ":" + "\n"); sb.append(pp.indent(mIndentSize + 12) + mResource.getString( PrettyPrintResources.TOKEN_IDENTIFIER) + attr.getOid().toString() + "\n"); sb.append(pp.indent(mIndentSize + 12) + mResource.getString( PrettyPrintResources.TOKEN_VALUES)); Enumeration values = attr.getValues(); if (values == null || !values.hasMoreElements()) { sb.append(mResource.getString( PrettyPrintResources.TOKEN_NONE) + "\n"); } else { for (int k = 0; values.hasMoreElements(); k++) { String v = values.nextElement(); if (k != 0) sb.append(","); sb.append(v); } } sb.append("\n"); } } return sb.toString(); } catch (Throwable e) { return ""; } } private String getCertificatePoliciesExtension() { StringBuffer sb = new StringBuffer(); try { sb.append(pp.indent(mIndentSize) + mResource.getString( PrettyPrintResources.TOKEN_IDENTIFIER)); sb.append(mResource.getString(PrettyPrintResources.TOKEN_CERT_POLICIES) + "- " + mExt.getExtensionId().toString() + "\n"); sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_CRITICAL)); if (mExt.isCritical()) { sb.append(mResource.getString( PrettyPrintResources.TOKEN_YES) + "\n"); } else { sb.append(mResource.getString( PrettyPrintResources.TOKEN_NO) + "\n"); } sb.append(pp.indent(mIndentSize + 4) + mResource.getString( PrettyPrintResources.TOKEN_CERT_POLICIES) + "\n"); CertificatePoliciesExtension cp = (CertificatePoliciesExtension) mExt; @SuppressWarnings("unchecked") Vector cpv = (Vector) cp.get("infos"); Enumeration e = cpv.elements(); if (e != null) { while (e.hasMoreElements()) { CertificatePolicyInfo cpi = e.nextElement(); sb.append(pp.indent(mIndentSize + 8) + "Policy Identifier: " + cpi.getPolicyIdentifier().getIdentifier().toString() + "\n"); PolicyQualifiers cpq = cpi.getPolicyQualifiers(); if (cpq != null) { for (int i = 0; i < cpq.size(); i++) { PolicyQualifierInfo pq = cpq.getInfoAt(i); Qualifier q = pq.getQualifier(); if (q instanceof CPSuri) { sb.append(pp.indent(mIndentSize + 12) + "Policy Qualifier Identifier: CPS Pointer Qualifier - " + pq.getId() + "\n"); sb.append(pp.indent(mIndentSize + 12) + "Policy Qualifier Data: " + ((CPSuri) q).getURI() + "\n"); } else if (q instanceof UserNotice) { sb.append(pp.indent(mIndentSize + 12) + "Policy Qualifier Identifier: CPS User Notice Qualifier - " + pq.getId() + "\n"); NoticeReference nref = ((UserNotice) q).getNoticeReference(); DisplayText dt = ((UserNotice) q).getDisplayText(); sb.append(pp.indent(mIndentSize + 12) + "Policy Qualifier Data: \n"); if (nref != null) { sb.append(pp.indent(mIndentSize + 16) + "Organization: " + nref.getOrganization().toString() + "\n"); sb.append(pp.indent(mIndentSize + 16) + "Notice Numbers: "); int[] nums = nref.getNumbers(); for (int k = 0; k < nums.length; k++) { if (k != 0) { sb.append(","); sb.append(nums[k]); } else { sb.append(nums[k]); } } sb.append("\n"); } if (dt != null) { sb.append(pp.indent(mIndentSize + 16) + "Explicit Text: " + dt.toString() + "\n"); } } } } } } return sb.toString(); } catch (IOException e) { return sb.toString(); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/IA5Charset.java000066400000000000000000000010731412550063600271700ustar00rootroot00000000000000package org.mozilla.jss.netscape.security.util; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; public class IA5Charset extends Charset { public IA5Charset() { super("ASN.1-IA5", null); } @Override public boolean contains(Charset cs) { return false; } @Override public CharsetDecoder newDecoder() { return new IA5CharsetDecoder(this); } @Override public CharsetEncoder newEncoder() { return new IA5CharsetEncoder(this); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/IA5CharsetDecoder.java000066400000000000000000000035701412550063600304620ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; /** * Converts bytes in ASN.1 IA5String character set to IA5String characters. * * @author Lily Hsiao * @author Slava Galperin */ public class IA5CharsetDecoder extends CharsetDecoder { public IA5CharsetDecoder(Charset cs) { super(cs, 1, 1); } @Override protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) { while (true) { if (in.remaining() < 1) return CoderResult.UNDERFLOW; in.mark(); byte b = in.get(); if (CodingErrorAction.REPORT == unmappableCharacterAction() && (b & 0x80) != 0) { return CoderResult.unmappableForLength(1); } if (out.remaining() < 1) { in.reset(); return CoderResult.OVERFLOW; } out.put((char) (b & 0x7f)); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/IA5CharsetEncoder.java000066400000000000000000000042061412550063600304710ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; /** * Converts characters in ASN.1 IA5String character set to IA5String bytes. * * @author Lily Hsiao * @author Slava Galperin */ public class IA5CharsetEncoder extends CharsetEncoder { public IA5CharsetEncoder(Charset cs) { super(cs, 1, 1); } /* * Converts an array of Unicode characters into an array of IA5String * bytes and returns the conversion result. * @param in input character buffer to convert. * @param out byte buffer to store output. * @return encoding result. */ @Override protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) { while (true) { if (in.remaining() < 1) return CoderResult.UNDERFLOW; in.mark(); char c = in.get(); if (CodingErrorAction.REPORT == unmappableCharacterAction() && (c & 0xFF80) != 0) { return CoderResult.unmappableForLength(1); } if (out.remaining() < 1) { in.reset(); return CoderResult.OVERFLOW; } out.put((byte) (c & 0x7f)); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/ObjectIdentifier.java000066400000000000000000000371171412550063600305210ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.io.IOException; import java.io.Serializable; import java.math.BigInteger; import java.util.Hashtable; import java.util.StringTokenizer; /** * Represent an ISO Object Identifier. * *

* Object Identifiers are arbitrary length hierarchical identifiers. The individual components are numbers, and they * define paths from the root of an ISO-managed identifier space. You will sometimes see a string name used instead of * (or in addition to) the numerical id. These are synonyms for the numerical IDs, but are not widely used since most * sites do not know all the requisite strings, while all sites can parse the numeric forms. * *

* So for example, JavaSoft has the sole authority to assign the meaning to identifiers below the 1.3.6.1.4.42.2.17 node * in the hierarchy, and other organizations can easily acquire the ability to assign such unique identifiers. * * @version 1.23 * * @author David Brownell * @author Amit Kapoor * @author Hemma Prafullchandra */ final public class ObjectIdentifier implements Serializable { /** use serialVersionUID from JDK 1.1. for interoperability */ private static final long serialVersionUID = 8697030238860181294L; /** * Constructs an object identifier from a string. This string * should be of the form 1.23.34.45.56 etc. */ public ObjectIdentifier(String oid) { if (oid == null) return; int ch = '.'; int start = 0; int end = 0; // Calculate length of oid componentLen = 0; while ((end = oid.indexOf(ch, start)) != -1) { start = end + 1; componentLen += 1; } componentLen += 1; components = new BigInteger[componentLen]; start = 0; int i = 0; String comp = null; while ((end = oid.indexOf(ch, start)) != -1) { comp = oid.substring(start, end); components[i++] = new BigInteger(comp); start = end + 1; } comp = oid.substring(start); components[i] = new BigInteger(comp); } /** * Constructs an object ID from an array of integers. This * is used to construct constant object IDs. */ public ObjectIdentifier(int values[]) { try { componentLen = values.length; BigInteger[] tmp = new BigInteger[componentLen]; for (int i = 0; i < componentLen; i++) { tmp[i] = BigInteger.valueOf(values[i]); } components = tmp.clone(); } catch (Throwable t) { System.out.println("X509.ObjectIdentifier(), no cloning!"); } } public ObjectIdentifier(BigInteger values[]) { try { componentLen = values.length; componentLen = values.length; BigInteger[] tmp = new BigInteger[componentLen]; for (int i = 0; i < componentLen; i++) { tmp[i] = new BigInteger(values[i].toString()); } components = tmp.clone(); } catch(Throwable t) { System.out.println("X509.ObjectIdentifier(), no cloning!"); } } /** * Constructs an object ID from an array of longs This * is used to construct constant object IDs. */ public ObjectIdentifier(long values[]) { try { componentLen = values.length; BigInteger[] tmp = new BigInteger[componentLen]; for (int i = 0; i < componentLen; i++) { tmp[i] = BigInteger.valueOf(values[i]); } components = tmp.clone(); } catch (Throwable t) { System.out.println("X509.ObjectIdentifier(), no cloning!"); } } /** * Constructs an object ID from an ASN.1 encoded input stream. * The encoding of the ID in the stream uses "DER", a BER/1 subset. * In this case, that means a triple { typeId, length, data }. * *

* NOTE: When an exception is thrown, the input stream has not been returned to its "initial" * state. * * @param in DER-encoded data holding an object ID * @exception IOException indicates a decoding error */ public ObjectIdentifier(DerInputStream in) throws IOException { byte type_id; int bufferEnd; /* * Object IDs are a "universal" type, and their tag needs only * one byte of encoding. Verify that the tag of this datum * is that of an object ID. * * Then get and check the length of the ID's encoding. We set * up so that we can use in.available() to check for the end of * this value in the data stream. */ type_id = (byte) in.getByte(); if (type_id != DerValue.tag_ObjectId) throw new IOException( "X509.ObjectIdentifier() -- data isn't an object ID" + " (tag = " + type_id + ")"); bufferEnd = in.available() - in.getLength() - 1; if (bufferEnd < 0) throw new IOException( "X509.ObjectIdentifier() -- not enough data"); initFromEncoding(in, bufferEnd); } /* * Build the OID from the rest of a DER input buffer; the tag * and length have been removed/verified */ ObjectIdentifier(DerInputBuffer buf) throws IOException { initFromEncoding(new DerInputStream(buf), 0); } /* * Helper function -- get the OID from a stream, after tag and * length are verified. */ private void initFromEncoding(DerInputStream in, int bufferEnd) throws IOException { /* * Now get the components ("sub IDs") one at a time. We fill a * temporary buffer, resizing it as needed. */ BigInteger component; boolean first_subid = true; for (components = new BigInteger[allocationQuantum], componentLen = 0; in.available() > bufferEnd;) { component = getComponentBigInt(in); if (first_subid) { long X, Y; /* * The ISO root has three children (0, 1, 2) and those nodes * aren't allowed to assign IDs larger than 39. These rules * are memorialized by some special casing in the BER encoding * of object IDs ... or maybe it's vice versa. * * NOTE: the allocation quantum is large enough that we know * we don't have to reallocate here! */ if (component.intValue() < 40) X = 0; else if (component.intValue() < 80) X = 1; else X = 2; Y = component.intValue() - (X * 40); components[0] = BigInteger.valueOf(X); components[1] = BigInteger.valueOf(Y); componentLen = 2; first_subid = false; } else { /* * Other components are encoded less exotically. The only * potential trouble is the need to grow the array. */ if (componentLen >= components.length) { BigInteger tmp_components[]; tmp_components = new BigInteger[components.length + allocationQuantum]; System.arraycopy(components, 0, tmp_components, 0, components.length); components = tmp_components; } components[componentLen++] = component; } } /* * Final sanity check -- if we didn't use exactly the number of bytes * specified, something's quite wrong. */ if (in.available() != bufferEnd) { throw new IOException( "X509.ObjectIdentifier() -- malformed input data"); } } /* * n.b. the only public interface is DerOutputStream.putOID() */ public void encode(DerOutputStream out) throws IOException { DerOutputStream bytes = new DerOutputStream(); int i; /* We can use the int here because we know we are dealing with small numbers for the first byte */ bytes.write((components[0].intValue() * 40) + components[1].intValue()); for (i = 2; i < componentLen; i++) putComponentBigInt(bytes, components[i]); /* * Now that we've constructed the component, encode * it in the stream we were given. */ out.write(DerValue.tag_ObjectId, bytes); } /* * Tricky OID component parsing technique ... note that one bit * per octet is lost, this returns at most 28 bits of component. * Also, notice this parses in big-endian format. */ private static BigInteger getComponentBigInt(DerInputStream in) throws IOException { BigInteger retval = BigInteger.valueOf(0); int tmp; while (true) { retval = retval.shiftLeft(7); tmp = in.getByte(); retval = retval.or(BigInteger.valueOf(tmp & 0x07f)); if ((tmp & 0x080) == 0) return retval; } } /* * Reverse of the above routine. Notice it needs to emit in * big-endian form, so it buffers the output until it's ready. * (Minimum length encoding is a DER requirement.) */ private static void putComponentBigInt(DerOutputStream out, BigInteger val) throws IOException { int i; int blockSize = 100; byte buf[] = new byte[blockSize]; BigInteger bigInt7f = BigInteger.valueOf(0x7f); BigInteger cur = new BigInteger(val.toString()); for (i = 0;; i++) { buf[i] = (cur.and(bigInt7f).byteValue()); cur = cur.shiftRight(7); if (cur.compareTo(BigInteger.ZERO) == 0 ) break; } for (; i > 0; --i) out.write(buf[i] | 0x080); out.write(buf[0]); } // XXX this API should probably facilitate the JDK sort utility /** * Compares this identifier with another, for sorting purposes. * An identifier does not precede itself. * * @param other identifer that may precede this one. * @return true iff other precedes this one * in a particular sorting order. */ public boolean precedes(ObjectIdentifier other) { int i; // shorter IDs go first if (other == this || componentLen < other.componentLen) return false; if (other.componentLen < componentLen) return true; // for each component, the lesser component goes first for (i = 0; i < componentLen; i++) { if (other.components[i].compareTo(components[i]) > 0) return true; } // identical IDs don't precede each other return false; } @Override public boolean equals(Object other) { if (other instanceof ObjectIdentifier) return equals((ObjectIdentifier) other); else return false; } /** * Compares this identifier with another, for equality. * * @return true iff the names are identical. */ public boolean equals(ObjectIdentifier other) { int i; if (other == this) return true; if (componentLen != other.componentLen) return false; for (i = 0; i < componentLen; i++) { if (components[i].compareTo(other.components[i]) != 0 ) return false; } return true; } @Override public int hashCode() { int h = 0; int oflow = 0; for (int i = 0; i < componentLen; i++) { oflow = (h & 0xff800000) >> 23; h <<= 9; h += components[i].intValue(); h ^= oflow; } return h; } /** * Returns a string form of the object ID. The format is the * conventional "dot" notation for such IDs, without any * user-friendly descriptive strings, since those strings * will not be understood everywhere. */ @Override public String toString() { StringBuffer retval = new StringBuffer(); int i; for (i = 0; i < componentLen; i++) { if (i != 0) retval.append("."); retval.append(components[i]); } return retval.toString(); } /* * To simplify, we assume no individual component of an object ID is * larger than 64 bits. Then we represent the path from the root as * an array that's (usually) only filled at the beginning. */ private BigInteger components[]; // path from root private int componentLen; // how much is used. private static final int allocationQuantum = 5; // >= 2 /** * Netscape Enhancement: * This function implements a object identifier factory. It * should help reduces in-memory Object Identifier object. * This function also provide additional checking on the OID. * A valid OID should start with 0, 1, or 2. * * Notes: * This function never returns null. IOException is raised * in error conditions. */ public static Hashtable mOIDs = new Hashtable(); public static ObjectIdentifier getObjectIdentifier(String oid) throws IOException { int value; if (oid == null) throw new IOException("empty object identifier"); oid = oid.trim(); ObjectIdentifier thisOID = mOIDs.get(oid); if (thisOID != null) return thisOID; StringTokenizer token = new StringTokenizer(oid, "."); value = Integer.valueOf(token.nextToken()); /* First token should be 0, 1, 2 */ if (value >= 0 && value <= 2) { value = Integer.valueOf(token.nextToken()); /* Second token should be 0 <= && >= 39 */ if (value >= 0 && value <= 39) { thisOID = new ObjectIdentifier(oid); if (thisOID.toString().equals(oid)) { mOIDs.put(oid, thisOID); return thisOID; } throw new IOException("invalid oid " + oid); } else throw new IOException("invalid oid " + oid); } else throw new IOException("invalid oid " + oid); } public static ObjectIdentifier getObjectIdentifier(int values[]) throws IOException { StringBuffer retval = new StringBuffer(); int i; for (i = 0; i < values.length; i++) { if (i != 0) retval.append("."); retval.append(values[i]); } return getObjectIdentifier(retval.toString()); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/PrettyPrintFormat.java000066400000000000000000000122311412550063600307530ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; /** * This class will display the certificate content in predefined * format. * * @author Andrew Wnuk * @version $Revision$, $Date$ */ public class PrettyPrintFormat { /*========================================================== * variables *==========================================================*/ private String mSeparator = ""; private int mIndentSize = 0; private int mLineLen = 0; /*========================================================== * constants * *==========================================================*/ private final static String spaces = " " + " " + " " + " " + " "; /*========================================================== * constructors *==========================================================*/ public PrettyPrintFormat(String separator) { mSeparator = separator; } public PrettyPrintFormat(String separator, int lineLen) { mSeparator = separator; mLineLen = lineLen; } public PrettyPrintFormat(String separator, int lineLen, int indentSize) { mSeparator = separator; mLineLen = lineLen; mIndentSize = indentSize; } /*========================================================== * Private methods *==========================================================*/ /*========================================================== * public methods *==========================================================*/ /** * Provide white space indention * stevep - speed improvements. Factor of 10 improvement * * @param size number of white space to be returned * @return white spaces */ public String indent(int size) { return spaces.substring(0, size); } private static final char[] hexdigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; /** * Convert Byte Array to Hex String Format * stevep - speedup by factor of 8 * * @param in byte array of data to hexify * @param indentSize number of spaces to prepend before each line * @param lineLen number of bytes to output on each line (0 * means: put everything on one line * @param separator the first character of this string will be used as * the separator between bytes. * @return string representation */ public String toHexString(byte[] in, int indentSize, int lineLen, String separator) { if (in == null) { return ""; } StringBuffer sb = new StringBuffer(); int hexCount = 0; char c[]; int j = 0; if (lineLen == 0) { c = new char[in.length * 3 + 1]; } else { c = new char[lineLen * 3 + 1]; } char sep = separator.charAt(0); sb.append(indent(indentSize)); for (int i = 0; i < in.length; i++) { if (lineLen > 0 && hexCount == lineLen) { c[j++] = '\n'; sb.append(c, 0, j); sb.append(indent(indentSize)); hexCount = 0; j = 0; } byte x = in[i]; // output hex digits to buffer c[j++] = hexdigits[(char) ((x >> 4) & 0xf)]; c[j++] = hexdigits[(char) (x & 0xf)]; // if not last char, output separator if (i != in.length - 1) { c[j++] = sep; } hexCount++; } if (j > 0) { c[j++] = '\n'; sb.append(c, 0, j); } // sb.append("\n"); return sb.toString(); } public String toHexString(byte[] in, int indentSize, int lineLen) { return toHexString(in, indentSize, lineLen, mSeparator); } public String toHexString(byte[] in, int indentSize) { return toHexString(in, indentSize, mLineLen); } public String toHexString(byte[] in) { return toHexString(in, mIndentSize); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/PrettyPrintResources.java000066400000000000000000000365361412550063600315130ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.util.ListResourceBundle; import org.mozilla.jss.netscape.security.extensions.NSCertTypeExtension; import org.mozilla.jss.netscape.security.x509.KeyUsageExtension; /** * Resource Boundle for the Pretty Print * * @author Jack Pan-Chen * @version $Revision$, $Date$ */ public class PrettyPrintResources extends ListResourceBundle { /** * Returns content */ @Override public Object[][] getContents() { return contents; } /** * Constants. The suffix represents the number of * possible parameters. */ //certificate pretty print public final static String TOKEN_CERTIFICATE = "tokenCertificate"; public final static String TOKEN_DATA = "tokenData"; public final static String TOKEN_VERSION = "tokenVersion"; public final static String TOKEN_SERIAL = "tokenSerial"; public final static String TOKEN_SIGALG = "tokenSignatureAlgorithm"; public final static String TOKEN_ISSUER = "tokenIssuer"; public final static String TOKEN_VALIDITY = "tokenValidity"; public final static String TOKEN_NOT_BEFORE = "tokenNotBefore"; public final static String TOKEN_NOT_AFTER = "tokenNotAfter"; public final static String TOKEN_SUBJECT = "tokenSubject"; public final static String TOKEN_SPKI = "tokenSPKI"; public final static String TOKEN_ALGORITHM = "tokenAlgorithm"; public final static String TOKEN_PUBLIC_KEY = "tokenPublicKey"; public final static String TOKEN_PUBLIC_KEY_MODULUS = "tokenPublicKeyModulus"; public final static String TOKEN_PUBLIC_KEY_EXPONENT = "tokenPublicKeyExponent"; public final static String TOKEN_EXTENSIONS = "tokenExtensions"; public final static String TOKEN_SIGNATURE = "tokenSignature"; //extension pretty print public final static String TOKEN_YES = "tokenYes"; public final static String TOKEN_NO = "tokenNo"; public final static String TOKEN_IDENTIFIER = "tokenIdentifier"; public final static String TOKEN_CRITICAL = "tokenCritical"; public final static String TOKEN_VALUE = "tokenValue"; //specific extension token public final static String TOKEN_KEY_TYPE = "tokenKeyType"; public final static String TOKEN_CERT_TYPE = "tokenCertType"; public final static String TOKEN_SKI = "tokenSKI"; public final static String TOKEN_AKI = "tokenAKI"; public final static String TOKEN_ACCESS_DESC = "tokenAccessDesc"; public final static String TOKEN_OCSP_NOCHECK = "tokenOcspNoCheck"; public final static String TOKEN_EXTENDED_KEY_USAGE = "tokenExtendedKeyUsage"; public final static String TOKEN_PRIVATE_KEY_USAGE = "tokenPrivateKeyUsage"; public final static String TOKEN_PRESENCE_SERVER = "tokenPresenceServer"; public final static String TOKEN_AIA = "tokenAIA"; public final static String TOKEN_CERT_POLICIES = "tokenCertPolicies"; public final static String TOKEN_SIA = "tokenSIA"; public final static String TOKEN_KEY_USAGE = "tokenKeyUsage"; public final static String TOKEN_CERT_USAGE = "tokenCertUsage"; public final static String TOKEN_KEY_ID = "tokenKeyId"; public final static String TOKEN_AUTH_NAME = "tokenAuthName"; public final static String TOKEN_CRL = "tokenCRL"; public final static String TOKEN_THIS_UPDATE = "tokenThisUpdate"; public final static String TOKEN_NEXT_UPDATE = "tokenNextUpdate"; public final static String TOKEN_REVOKED_CERTIFICATES = "revokedCerts"; public final static String TOKEN_REVOCATION_DATE = "revocationDate"; public final static String TOKEN_REVOCATION_REASON = "revocationReason"; public final static String TOKEN_REASON = "reason"; public final static String TOKEN_BASIC_CONSTRAINTS = "basicConstraints"; public final static String TOKEN_NAME_CONSTRAINTS = "tokenNameConstraints"; public final static String TOKEN_NSC_COMMENT = "tokenNSCComment"; public final static String TOKEN_IS_CA = "isCA"; public final static String TOKEN_PATH_LEN = "pathLen"; public final static String TOKEN_PATH_LEN_UNLIMITED = "pathLenUnlimited"; public final static String TOKEN_PATH_LEN_UNDEFINED = "pathLenUndefined"; public final static String TOKEN_PATH_LEN_INVALID = "pathLenInvalid"; public final static String TOKEN_CRL_NUMBER = "CRLNumber"; public final static String TOKEN_NUMBER = "Number"; public final static String TOKEN_DELTA_CRL_INDICATOR = "DeltaCRLIndicator"; public final static String TOKEN_BASE_CRL_NUMBER = "BaseCRLNumber"; public final static String TOKEN_CERT_SCOPE_OF_USE = "CertificateScopeOfUse"; public final static String TOKEN_SCOPE_OF_USE = "ScopeOfUse"; public final static String TOKEN_PORT = "Port"; public final static String TOKEN_ISSUER_ALT_NAME = "IssuerAlternativeName"; public final static String TOKEN_ISSUER_NAMES = "IssuerNames"; public final static String TOKEN_SUBJECT_ALT_NAME = "SubjectAlternativeName"; public final static String TOKEN_SUBJECT_NAME = "SubjectName"; public final static String TOKEN_DECODING_ERROR = "decodingError"; public final static String TOKEN_FRESHEST_CRL_EXT = "FreshestCRL"; public final static String TOKEN_INHIBIT_ANY_POLICY_EXT = "InhibitAnyPolicy"; public final static String TOKEN_SKIP_CERTS = "SkipCerts"; public final static String TOKEN_CRL_DP_EXT = "CRLDistributionPoints"; public final static String TOKEN_CRLDP_NUMPOINTS = "CRLDP_NUMPOINTS"; public final static String TOKEN_CRLDP_POINTN = "CRLDP_POINTN"; public final static String TOKEN_CRLDP_DISTPOINT = "CRLDP_DISTPOINT"; public final static String TOKEN_CRLDP_REASONS = "CRLDP_REASONS"; public final static String TOKEN_CRLDP_CRLISSUER = "CRLDP_CRLISSUER"; public final static String TOKEN_ISSUING_DIST_POINT = "IssuingDistributionPoint"; public final static String TOKEN_DIST_POINT_NAME = "DistributionPointName"; public final static String TOKEN_FULL_NAME = "FullName"; public final static String TOKEN_RELATIVE_NAME = "NameRelativeToCRLIssuer"; public final static String TOKEN_ONLY_USER_CERTS = "OnlyContainsUserCerts"; public final static String TOKEN_ONLY_CA_CERTS = "OnlyContainsCACerts"; public final static String TOKEN_ONLY_SOME_REASONS = "OnlySomeReasons"; public final static String TOKEN_INDIRECT_CRL = "IndirectCRL"; public final static String TOKEN_INVALIDITY_DATE = "invalidityDate"; public final static String TOKEN_DATE_OF_INVALIDITY = "dateOfInvalidity"; public final static String TOKEN_CERTIFICATE_ISSUER = "CertificateIssuer"; public final static String TOKEN_HOLD_INSTRUCTION = "HoldInstruction"; public final static String TOKEN_HOLD_INSTRUCTION_CODE = "HoldInstructionCode"; public final static String TOKEN_POLICY_CONSTRAINTS = "PolicyConstraints"; public final static String TOKEN_POLICY_MAPPINGS = "PolicyMappings"; public final static String TOKEN_SUBJECT_DIR_ATTR = "SubjectDirectoryAttributes"; // policy constriants extension fields public final static String TOKEN_INHIBIT_POLICY_MAPPING = "inhibitPolicyMapping"; public final static String TOKEN_REQUIRE_EXPLICIT_POLICY = "requireExplicitPolicy"; // policy mappings extension fields public final static String TOKEN_MAPPINGS = "mappings"; public final static String TOKEN_MAP = "map"; public final static String TOKEN_ISSUER_DOMAIN_POLICY = "issuerDomainPolicy"; public final static String TOKEN_SUBJECT_DOMAIN_POLICY = "subjectDomainPolicy"; // subject directory attribute fields public final static String TOKEN_ATTRIBUTES = "Attributes"; public final static String TOKEN_ATTRIBUTE = "Attribute"; public final static String TOKEN_VALUES = "Values"; // field values public final static String TOKEN_NOT_SET = "notSet"; public final static String TOKEN_NONE = "none"; public final static String TOKEN_CACHE_NOT_AVAILABLE = "cacheNotAvailable"; public final static String TOKEN_CACHE_IS_EMPTY = "cacheIsEmpty"; //Tokens should have blank_space as trailer static final Object[][] contents = { { TOKEN_CERTIFICATE, "Certificate: " }, { TOKEN_DATA, "Data: " }, { TOKEN_VERSION, "Version: " }, { TOKEN_SERIAL, "Serial Number: " }, { TOKEN_SIGALG, "Signature Algorithm: " }, { TOKEN_ISSUER, "Issuer: " }, { TOKEN_VALIDITY, "Validity: " }, { TOKEN_NOT_BEFORE, "Not Before: " }, { TOKEN_NOT_AFTER, "Not After: " }, { TOKEN_SUBJECT, "Subject: " }, { TOKEN_SPKI, "Subject Public Key Info: " }, { TOKEN_ALGORITHM, "Algorithm: " }, { TOKEN_PUBLIC_KEY, "Public Key: " }, { TOKEN_PUBLIC_KEY_MODULUS, "Public Key Modulus: " }, { TOKEN_PUBLIC_KEY_EXPONENT, "Exponent: " }, { TOKEN_EXTENSIONS, "Extensions: " }, { TOKEN_SIGNATURE, "Signature: " }, { TOKEN_YES, "yes " }, { TOKEN_NO, "no " }, { TOKEN_IDENTIFIER, "Identifier: " }, { TOKEN_CRITICAL, "Critical: " }, { TOKEN_VALUE, "Value: " }, { TOKEN_KEY_TYPE, "Key Type " }, { TOKEN_CERT_TYPE, "Netscape Certificate Type " }, { TOKEN_SKI, "Subject Key Identifier " }, { TOKEN_AKI, "Authority Key Identifier " }, { TOKEN_ACCESS_DESC, "Access Description: " }, { TOKEN_OCSP_NOCHECK, "OCSP NoCheck: " }, { TOKEN_EXTENDED_KEY_USAGE, "Extended Key Usage: " }, { TOKEN_PRIVATE_KEY_USAGE, "Private Key Usage: " }, { TOKEN_PRESENCE_SERVER, "Presence Server: " }, { TOKEN_AIA, "Authority Info Access: " }, { TOKEN_CERT_POLICIES, "Certificate Policies: " }, { TOKEN_SIA, "Subject Info Access: " }, { TOKEN_KEY_USAGE, "Key Usage: " }, { KeyUsageExtension.DIGITAL_SIGNATURE, "Digital Signature " }, { KeyUsageExtension.NON_REPUDIATION, "Non Repudiation " }, { KeyUsageExtension.KEY_ENCIPHERMENT, "Key Encipherment " }, { KeyUsageExtension.DATA_ENCIPHERMENT, "Data Encipherment " }, { KeyUsageExtension.KEY_AGREEMENT, "Key Agreement " }, { KeyUsageExtension.KEY_CERTSIGN, "Key CertSign " }, { KeyUsageExtension.CRL_SIGN, "Crl Sign " }, { KeyUsageExtension.ENCIPHER_ONLY, "Encipher Only " }, { KeyUsageExtension.DECIPHER_ONLY, "Decipher Only " }, { TOKEN_CERT_USAGE, "Certificate Usage: " }, { NSCertTypeExtension.SSL_CLIENT, "SSL Client " }, { NSCertTypeExtension.SSL_SERVER, "SSL Server " }, { NSCertTypeExtension.EMAIL, "Secure Email " }, { NSCertTypeExtension.OBJECT_SIGNING, "Object Signing " }, { NSCertTypeExtension.SSL_CA, "SSL CA " }, { NSCertTypeExtension.EMAIL_CA, "Secure Email CA " }, { NSCertTypeExtension.OBJECT_SIGNING_CA, "ObjectSigning CA " }, { TOKEN_KEY_ID, "Key Identifier: " }, { TOKEN_AUTH_NAME, "Authority Name: " }, { TOKEN_CRL, "Certificate Revocation List: " }, { TOKEN_THIS_UPDATE, "This Update: " }, { TOKEN_NEXT_UPDATE, "Next Update: " }, { TOKEN_REVOKED_CERTIFICATES, "Revoked Certificates: " }, { TOKEN_REVOCATION_DATE, "Revocation Date: " }, { TOKEN_REVOCATION_REASON, "Revocation Reason " }, { TOKEN_REASON, "Reason: " }, { TOKEN_BASIC_CONSTRAINTS, "Basic Constraints " }, { TOKEN_NAME_CONSTRAINTS, "Name Constraints " }, { TOKEN_NSC_COMMENT, "Netscape Comment " }, { TOKEN_IS_CA, "Is CA: " }, { TOKEN_PATH_LEN, "Path Length Constraint: " }, { TOKEN_PATH_LEN_UNLIMITED, "UNLIMITED" }, { TOKEN_PATH_LEN_UNDEFINED, "UNDEFINED" }, { TOKEN_PATH_LEN_INVALID, "INVALID" }, { TOKEN_CRL_NUMBER, "CRL Number " }, { TOKEN_NUMBER, "Number: " }, { TOKEN_DELTA_CRL_INDICATOR, "Delta CRL Indicator " }, { TOKEN_BASE_CRL_NUMBER, "Base CRL Number: " }, { TOKEN_CERT_SCOPE_OF_USE, "Certificate Scope of Use " }, { TOKEN_SCOPE_OF_USE, "Scope of Use: " }, { TOKEN_PORT, "Port: " }, { TOKEN_ISSUER_ALT_NAME, "Issuer Alternative Name " }, { TOKEN_ISSUER_NAMES, "Issuer Names: " }, { TOKEN_SUBJECT_ALT_NAME, "Subject Alternative Name " }, { TOKEN_DECODING_ERROR, "Decoding Error" }, { TOKEN_FRESHEST_CRL_EXT, "Freshest CRL " }, { TOKEN_INHIBIT_ANY_POLICY_EXT, "Inhibit Any-Policy " }, { TOKEN_SKIP_CERTS, "Skip Certs: " }, { TOKEN_CRL_DP_EXT, "CRL Distribution Points " }, { TOKEN_CRLDP_NUMPOINTS, "Number of Points: " }, { TOKEN_CRLDP_POINTN, "Point " }, { TOKEN_CRLDP_DISTPOINT, "Distribution Point: " }, { TOKEN_CRLDP_REASONS, "Reason Flags: " }, { TOKEN_CRLDP_CRLISSUER, "CRL Issuer: " }, { TOKEN_ISSUING_DIST_POINT, "Issuing Distribution Point " }, { TOKEN_DIST_POINT_NAME, "Distribution Point: " }, { TOKEN_FULL_NAME, "Full Name: " }, { TOKEN_RELATIVE_NAME, "Name Relative To CRL Issuer: " }, { TOKEN_ONLY_USER_CERTS, "Only Contains User Certificates: " }, { TOKEN_ONLY_CA_CERTS, "Only Contains CA Certificates: " }, { TOKEN_ONLY_SOME_REASONS, "Only Some Reasons: " }, { TOKEN_INDIRECT_CRL, "Indirect CRL: " }, { TOKEN_INVALIDITY_DATE, "Invalidity Date " }, { TOKEN_DATE_OF_INVALIDITY, "Invalidity Date: " }, { TOKEN_CERTIFICATE_ISSUER, "Certificate Issuer " }, { TOKEN_HOLD_INSTRUCTION, "Hold Instruction Code " }, { TOKEN_HOLD_INSTRUCTION_CODE, "Hold Instruction Code: " }, { TOKEN_POLICY_CONSTRAINTS, "Policy Constraints " }, { TOKEN_INHIBIT_POLICY_MAPPING, "Inhibit Policy Mapping: " }, { TOKEN_REQUIRE_EXPLICIT_POLICY, "Require Explicit Policy: " }, { TOKEN_POLICY_MAPPINGS, "Policy Mappings " }, { TOKEN_MAPPINGS, "Mappings: " }, { TOKEN_MAP, "Map " }, { TOKEN_ISSUER_DOMAIN_POLICY, "Issuer Domain Policy: " }, { TOKEN_SUBJECT_DOMAIN_POLICY, "Subject Domain Policy: " }, { TOKEN_SUBJECT_DIR_ATTR, "Subject Directory Attributes " }, { TOKEN_ATTRIBUTES, "Attributes:" }, { TOKEN_ATTRIBUTE, "Attribute " }, { TOKEN_VALUES, "Values: " }, { TOKEN_NOT_SET, "not set" }, { TOKEN_NONE, "none" }, { TOKEN_CACHE_NOT_AVAILABLE, "CRL cache is not available. " }, { TOKEN_CACHE_IS_EMPTY, "CRL cache is empty. " }, }; } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/PrintableCharset.java000066400000000000000000000022771412550063600305410ustar00rootroot00000000000000package org.mozilla.jss.netscape.security.util; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; public class PrintableCharset extends Charset { public PrintableCharset() { super("ASN.1-Printable", null); } public static boolean isPrintableChar(char c) { if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') && (c < '0' || c > '9') && (c != ' ') && (c != '\'') && (c != '(') && (c != ')') && (c != '+') && (c != ',') && (c != '-') && (c != '.') && (c != '/') && (c != ':') && (c != '=') && (c != '?')) { return false; } else { return true; } } @Override public boolean contains(Charset cs) { return false; } @Override public CharsetDecoder newDecoder() { return new PrintableCharsetDecoder(this); } @Override public CharsetEncoder newEncoder() { return new PrintableCharsetEncoder(this); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/PrintableCharsetDecoder.java000066400000000000000000000040711412550063600320210ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; /** * Converts bytes in ASN.1 PrintableString character set to PrintableString * characters. * * @author Lily Hsiao * @author Slava Galperin */ public class PrintableCharsetDecoder extends CharsetDecoder { public PrintableCharsetDecoder(Charset cs) { super(cs, 1, 1); } @Override protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) { while (true) { if (in.remaining() < 1) return CoderResult.UNDERFLOW; in.mark(); byte b = in.get(); char c = (char) (b & 0x7f); if (CodingErrorAction.REPORT == unmappableCharacterAction() && !PrintableCharset.isPrintableChar(c)) { /* "bug" fix for 359010 return CoderResult.unmappableForLength(1); */ continue; } if (out.remaining() < 1) { in.reset(); return CoderResult.OVERFLOW; } out.put(c); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/PrintableCharsetEncoder.java000066400000000000000000000043161412550063600320350ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; /** * Converts characters in ASN.1 PrintableString character set to PrintableString * bytes. * * @author Lily Hsiao * @author Slava Galperin */ public class PrintableCharsetEncoder extends CharsetEncoder { public PrintableCharsetEncoder(Charset cs) { super(cs, 1, 1); } /* * Converts an array of Unicode characters into an array of PrintableString * bytes and returns the conversion result. * @param in input character buffer to convert. * @param out byte buffer to store output. * @return encoding result. */ @Override protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) { while (true) { if (in.remaining() < 1) return CoderResult.UNDERFLOW; in.mark(); char c = in.get(); if (CodingErrorAction.REPORT == unmappableCharacterAction() && !PrintableCharset.isPrintableChar(c)) { return CoderResult.unmappableForLength(1); } if (out.remaining() < 1) { in.reset(); return CoderResult.OVERFLOW; } out.put((byte) (c & 0x7f)); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/PubKeyPrettyPrint.java000066400000000000000000000106711412550063600307300ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.security.InvalidKeyException; import java.security.PublicKey; import java.util.Locale; import java.util.ResourceBundle; import org.mozilla.jss.netscape.security.provider.RSAPublicKey; import org.mozilla.jss.netscape.security.x509.X509Key; /** * This class will display the certificate content in predefined * format. * * @author Jack Pan-Chen * @author Andrew Wnuk * @version $Revision$, $Date$ */ public class PubKeyPrettyPrint { /*========================================================== * variables *==========================================================*/ private X509Key mX509Key = null; private PrettyPrintFormat pp = null; /*========================================================== * constructors *==========================================================*/ public PubKeyPrettyPrint(PublicKey key) { if (key instanceof X509Key) mX509Key = (X509Key) key; pp = new PrettyPrintFormat(":"); } /*========================================================== * public methods *==========================================================*/ /** * This method return string representation of the certificate * in predefined format using specified client local. I18N Support. * * @param clientLocale Locale to be used for localization * @return string representation of the certificate */ public String toString(Locale clientLocale, int indentSize, int lineLen) { if (mX509Key != null) return X509toString(clientLocale, indentSize, lineLen); else return null; } public String X509toString(Locale clientLocale, int indentSize, int lineLen) { //get I18N resources ResourceBundle resource = ResourceBundle.getBundle( PrettyPrintResources.class.getName()); StringBuffer sb = new StringBuffer(); try { String alg = mX509Key.getAlgorithm(); //XXX I18N Algorithm Name ? sb.append(pp.indent(indentSize) + resource.getString( PrettyPrintResources.TOKEN_ALGORITHM) + alg + " - " + mX509Key.getAlgorithmId().getOID().toString() + "\n"); if (alg.equals("RSA")) { RSAPublicKey rsakey = new RSAPublicKey(mX509Key.getEncoded()); sb.append(pp.indent(indentSize) + resource.getString( PrettyPrintResources.TOKEN_PUBLIC_KEY) + "\n"); sb.append(pp.indent(indentSize + 4) + resource.getString( PrettyPrintResources.TOKEN_PUBLIC_KEY_EXPONENT) + rsakey.getPublicExponent().toInt() + "\n"); sb.append(pp.indent(indentSize + 4) + resource.getString( PrettyPrintResources.TOKEN_PUBLIC_KEY_MODULUS) + "(" + rsakey.getKeySize() + " bits) :\n"); sb.append(pp.toHexString( rsakey.getModulus().toByteArray(), indentSize + 8, lineLen)); } else { // DSAPublicKey is more complicated to decode, since // the DSAParams (PQG) is not fully decoded. // So, we just print the entire public key blob sb.append(pp.indent(indentSize) + resource.getString( PrettyPrintResources.TOKEN_PUBLIC_KEY) + "\n"); sb.append(pp.toHexString(mX509Key.getKey(), indentSize + 4, lineLen)); } } catch(InvalidKeyException e){ e.printStackTrace(); } return sb.toString(); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/UniversalCharset.java000066400000000000000000000011311412550063600305550ustar00rootroot00000000000000package org.mozilla.jss.netscape.security.util; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; public class UniversalCharset extends Charset { public UniversalCharset() { super("ASN.1-Universal", null); } @Override public boolean contains(Charset cs) { return false; } @Override public CharsetDecoder newDecoder() { return new UniversalCharsetDecoder(this); } @Override public CharsetEncoder newEncoder() { return new UniversalCharsetEncoder(this); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/UniversalCharsetDecoder.java000066400000000000000000000067161412550063600320610ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CoderResult; import java.nio.charset.CodingErrorAction; /** * Converts bytes in ASN.1 UniversalString character set to UniversalString * characters. * * @author Lily Hsiao * @author Slava Galperin */ public class UniversalCharsetDecoder extends CharsetDecoder { public UniversalCharsetDecoder(Charset cs) { super(cs, 0.25f, 1); } @Override protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) { while (true) { // XXX we do not know what to do with truly UCS-4 characters here // we also assumed network byte order if (in.remaining() < 4) return CoderResult.UNDERFLOW; in.mark(); byte b0 = in.get(); byte b1 = in.get(); byte b2 = in.get(); byte b3 = in.get(); if (CodingErrorAction.REPORT == unmappableCharacterAction() && !((b0 == 0 && b1 == 0) || (b2 == 0 && b3 == 0))) { return CoderResult.unmappableForLength(4); } char c; if (b2 == 0 && b3 == 0) { // Try to be a bit forgiving. If the byte order is // reversed, we still try handle it. // Sample Date Set (1): // 0000000 f 0 \0 \0 213 0 \0 \0 S 0 \0 \0 // 0000014 // Sample Date Set (2): // 0000000 w \0 \0 \0 w \0 \0 \0 w \0 \0 \0 . \0 \0 \0 // 0000020 ( \0 \0 \0 t \0 \0 \0 o \0 \0 \0 b \0 \0 \0 // 0000040 e \0 \0 \0 | \0 \0 \0 n \0 \0 \0 o \0 \0 \0 // 0000060 t \0 \0 \0 t \0 \0 \0 o \0 \0 \0 b \0 \0 \0 // 0000100 e \0 \0 \0 ) \0 \0 \0 . \0 \0 \0 c \0 \0 \0 // 0000120 o \0 \0 \0 m \0 \0 \0 // 0000130 c = (char) (((b1 << 8) & 0xff00) + (b0 & 0x00ff)); } else { // (b0 == 0 && b1 == 0) // This should be the right order. // // 0000000 0000 00c4 0000 0064 0000 006d 0000 0069 // 0000020 0000 006e 0000 0020 0000 0051 0000 0041 // 0000040 c = (char) (((b2 << 8) & 0xff00) + (b3 & 0x00ff)); } if (out.remaining() < 1) { in.reset(); return CoderResult.OVERFLOW; } out.put(c); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/UniversalCharsetEncoder.java000066400000000000000000000041321412550063600320610ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.nio.charset.CoderResult; /** * Converts characters in ASN.1 UniversalString character set to UniversalString * bytes. * * @author Lily Hsiao * @author Slava Galperin */ public class UniversalCharsetEncoder extends CharsetEncoder { public UniversalCharsetEncoder(Charset cs) { super(cs, 4, 4, new byte[] { 0, 0, 0, 0 }); } /* * Converts an array of Unicode characters into an array of UniversalString * bytes and returns the conversion result. * @param in input character buffer to convert. * @param out byte buffer to store output. * @return encoding result. */ @Override protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) { while (true) { if (in.remaining() < 1) return CoderResult.UNDERFLOW; in.mark(); char c = in.get(); if (out.remaining() < 4) { in.reset(); return CoderResult.OVERFLOW; } out.put((byte) 0); out.put((byte) 0); out.put((byte) ((c >> 8) & 0xff)); out.put((byte) (c & 0xff)); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/Utils.java000066400000000000000000000336031412550063600264040ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.util; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetAddress; import java.net.UnknownHostException; import java.text.SimpleDateFormat; import java.util.Base64; import java.util.Date; import java.util.StringTokenizer; import java.util.Vector; public class Utils { /** * Checks if this is NT. */ public static boolean isNT() { return File.separator.equals("\\"); } public static boolean isUnix() { return File.separator.equals("/"); } public static boolean exec(String cmd) { try { String cmds[] = null; if (isNT()) { // NT cmds = new String[3]; cmds[0] = "cmd"; cmds[1] = "/c"; cmds[2] = cmd; } else { // UNIX cmds = new String[3]; cmds[0] = "/bin/sh"; cmds[1] = "-c"; cmds[2] = cmd; } Process process = Runtime.getRuntime().exec(cmds); process.waitFor(); if (process.exitValue() == 0) { /** * pOut = new BufferedReader( * new InputStreamReader(process.getInputStream())); * while ((l = pOut.readLine()) != null) { * System.out.println(l); * } **/ return true; } else { /** * pOut = new BufferedReader( * new InputStreamReader(process.getErrorStream())); * l = null; * while ((l = pOut.readLine()) != null) { * System.out.println(l); * } **/ return false; } } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return false; } public static String readFromStream(InputStream inputStream) throws IOException { StringBuilder sb = new StringBuilder(); BufferedReader br = null; try { br = new BufferedReader(new InputStreamReader(inputStream)); String line = null; while ((line = br.readLine()) != null) { sb.append(line + System.getProperty("line.separator")); } } finally { br.close(); } return sb.toString().trim(); } public static void writeToStream(OutputStream outputStream, String input) throws IOException { BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream)); writer.write(input); writer.flush(); writer.close(); } /** * Utility method to execute system commands * * @param cmd The command to be executed and its arguments * @param input The stdin input to be passed to the cmd * @return stdout or stderr of the command executed * @throws IOException * @throws InterruptedException */ public static String exec(String[] cmd, String input) throws IOException, InterruptedException { ProcessBuilder pb = new ProcessBuilder(cmd); Process p = pb.start(); if (input != null) { writeToStream(p.getOutputStream(), input); } p.waitFor(); String output; if (p.exitValue() == 0) { output = readFromStream(p.getInputStream()); } else { output = readFromStream(p.getErrorStream()); } p.destroy(); return output; } public static String SpecialURLDecode(String s) { if (s == null) return null; ByteArrayOutputStream out = new ByteArrayOutputStream(s.length()); for (int i = 0; i < s.length(); i++) { int c = s.charAt(i); if (c == '+') { out.write(' '); } else if (c == '#') { int c1 = Character.digit(s.charAt(++i), 16); int c2 = Character.digit(s.charAt(++i), 16); out.write((char) (c1 * 16 + c2)); } else { out.write(c); } } // end for return out.toString(); } public static byte[] SpecialDecode(String s) { if (s == null) return null; ByteArrayOutputStream out = new ByteArrayOutputStream(s.length()); for (int i = 0; i < s.length(); i++) { int c = s.charAt(i); if (c == '+') { out.write(' '); } else if (c == '#') { int c1 = Character.digit(s.charAt(++i), 16); int c2 = Character.digit(s.charAt(++i), 16); out.write((char) (c1 * 16 + c2)); } else { out.write(c); } } // end for return out.toByteArray(); } public static String SpecialEncode(byte data[]) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < data.length; i++) { sb.append("%"); if ((data[i] & 0xff) < 16) { sb.append("0"); } sb.append(Integer.toHexString((data[i] & 0xff))); } return sb.toString().toUpperCase(); } public static String HexEncode(byte data[]) { StringBuffer sb = new StringBuffer(); if (data != null) { for (int i = 0; i < data.length; i++) { if ((data[i] & 0xff) < 16) { sb.append("0"); } sb.append(Integer.toHexString((data[i] & 0xff))); } } return sb.toString(); } public static void checkHost(String hostname) throws UnknownHostException { InetAddress.getByName(hostname); } public static void copy(String orig, String dest) throws Exception { BufferedReader in = null; PrintWriter out = null; try { in = new BufferedReader(new FileReader(orig)); out = new PrintWriter( new BufferedWriter(new FileWriter(dest))); String line = ""; while (in.ready()) { line = in.readLine(); if (line != null) out.println(line); } } catch (Exception ee) { ee.printStackTrace(); throw ee; } finally { if (in != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } if (out != null) { out.close(); } } } public static void copyStream(InputStream in, OutputStream out) throws IOException { byte[] buf = new byte[4096]; int len; while ((len = in.read(buf)) != -1) { out.write(buf, 0, len); } } public static void copyStream(BufferedReader in, OutputStreamWriter out) throws IOException { char[] buf = new char[4096]; int len; while ((len = in.read(buf)) != -1) { out.write(buf, 0, len); } } /// Sorts an array of Strings. // Java currently has no general sort function. Sorting Strings is // common enough that it's worth making a special case. public static void sortStrings(String[] strings) { // Just does a bubblesort. for (int i = 0; i < strings.length - 1; ++i) { for (int j = i + 1; j < strings.length; ++j) { if (strings[i].compareTo(strings[j]) > 0) { String t = strings[i]; strings[i] = strings[j]; strings[j] = t; } } } } /// Returns a date string formatted in Unix ls style - if it's within // six months of now, Mmm dd hh:ss, else Mmm dd yyyy. public static String lsDateStr(Date date) { long dateTime = date.getTime(); if (dateTime == -1L) return "------------"; long nowTime = System.currentTimeMillis(); SimpleDateFormat formatter = new SimpleDateFormat(); if (Math.abs(nowTime - dateTime) < 183L * 24L * 60L * 60L * 1000L) formatter.applyPattern("MMM dd hh:ss"); else formatter.applyPattern("MMM dd yyyy"); return formatter.format(date); } /** * compares contents two byte arrays returning true if exactly same. */ static public boolean byteArraysAreEqual(byte[] a, byte[] b) { if (a.length != b.length) return false; for (int i = 0; i < a.length; i++) { if (a[i] != b[i]) return false; } return true; } /** * strips out double quotes around String parameter * * @param s the string potentially bracketed with double quotes * @return string stripped of surrounding double quotes */ public static String stripQuotes(String s) { if (s == null) { return s; } if ((s.startsWith("\"")) && (s.endsWith("\""))) { return (s.substring(1, (s.length() - 1))); } return s; } /** * returns an array of strings from a vector of Strings * there'll be trouble if the Vector contains something other * than just Strings */ public static String[] getStringArrayFromVector(Vector v) { String s[] = new String[v.size()]; v.copyInto(s); return s; } /** * Converts a byte array into a Base-64 encoded string. * If the chunked option is true, the output will be split into * multiple lines. Otherwise, the output will be a single line. * * @param bytes byte array * @param chunked generate chunked output * @return base-64 encoded data */ public static String base64encode(byte[] bytes, boolean chunked) { if (chunked) { return base64encodeMultiLine(bytes); } else { return base64encodeSingleLine(bytes); } } /** * Converts a byte array into a multi-line Base-64 encoded string. * Each line is at most 64-character long and terminated with CRLF. * * @param bytes byte array * @return base-64 encoded data */ public static String base64encodeMultiLine(byte[] bytes) { // When switching from apache-commons-codec to the standard library, // the standard library does not include a final line separator at // the end of the encoded data. This results in malformed CSRs. return Base64.getMimeEncoder().encodeToString(bytes) + "\r\n"; } /** * Converts a byte array into a single-line Base-64 encoded string. * The line is not terminated with CRLF. * * @param bytes byte array * @return base-64 encoded data */ public static String base64encodeSingleLine(byte[] bytes) { return Base64.getEncoder().encodeToString(bytes); } /** * Converts a Base-64 encoded string into a byte array. * * @param string base-64 encoded data * @return byte array */ public static byte[] base64decode(String string) { try { // Java is particular about its base64. We already used the MIME // decoder as it was most flexible about whitespace. However, it // doesn't understand URL-encoded Base64 (using '-' instead of // '+' and '_' instead of '/'). So, detect those characters and // pass it to the correct decoder. if (string.contains("_") || string.contains("-")) { return Base64.getUrlDecoder().decode(string); } else { return Base64.getMimeDecoder().decode(string); } } catch (IllegalArgumentException iae) { return new byte[0]; } } /** * Normalize B64 input String * * @param string base-64 string * @return normalized string */ public static String normalizeString(String string) { return normalizeString(string, false); } /** * Normalize B64 input String * * @param string base-64 string * @param keepSpace a boolean variable to control whether to keep spaces or not * @return normalized string */ public static String normalizeString(String string, Boolean keepSpace) { if (string == null) { return string; } StringBuffer sb = new StringBuffer(); StringTokenizer st = null; if (keepSpace) st = new StringTokenizer(string, "\r\n"); else st = new StringTokenizer(string, "\r\n "); while (st.hasMoreTokens()) { String nextLine = st.nextToken(); nextLine = nextLine.trim(); sb.append(nextLine); } return sb.toString(); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/util/WrappingParams.java000066400000000000000000000262011412550063600302330ustar00rootroot00000000000000package org.mozilla.jss.netscape.security.util; import java.security.NoSuchAlgorithmException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.crypto.EncryptionAlgorithm; import org.mozilla.jss.crypto.IVParameterSpec; import org.mozilla.jss.crypto.KeyGenAlgorithm; import org.mozilla.jss.crypto.KeyWrapAlgorithm; import org.mozilla.jss.crypto.SymmetricKey; import org.mozilla.jss.crypto.SymmetricKey.Type; public class WrappingParams { // session key attributes SymmetricKey.Type skType; KeyGenAlgorithm skKeyGenAlgorithm; int skLength; // wrapping algorithm for session key KeyWrapAlgorithm skWrapAlgorithm; // Encryption algorithm for payload EncryptionAlgorithm payloadEncryptionAlgorithm; //wrapping algorithm for payload KeyWrapAlgorithm payloadWrapAlgorithm; // payload encryption IV IVParameterSpec payloadEncryptionIV; // payload wrapping IV IVParameterSpec payloadWrappingIV; public WrappingParams(Type skType, KeyGenAlgorithm skKeyGenAlgorithm, int skLength, KeyWrapAlgorithm skWrapAlgorithm, EncryptionAlgorithm payloadEncryptionAlgorithm, KeyWrapAlgorithm payloadWrapAlgorithm, IVParameterSpec payloadEncryptIV, IVParameterSpec payloadWrapIV) { super(); this.skType = skType; this.skKeyGenAlgorithm = skKeyGenAlgorithm; this.skLength = skLength; this.skWrapAlgorithm = skWrapAlgorithm; this.payloadEncryptionAlgorithm = payloadEncryptionAlgorithm; this.payloadWrapAlgorithm = payloadWrapAlgorithm; this.payloadEncryptionIV = payloadEncryptIV; this.payloadWrappingIV = payloadWrapIV; } public static EncryptionAlgorithm getEncryptionAlgorithmFromName(String name) throws Exception { String fields[] = name.split("//"); String alg = fields[0]; String mode = fields[1]; String padding = fields[2]; int strength = Integer.parseInt(fields[3]); return EncryptionAlgorithm.lookup(alg, mode, padding, strength); } public WrappingParams() {} public WrappingParams(String encryptOID, String wrapName, String priKeyAlgo, IVParameterSpec encryptIV, IVParameterSpec wrapIV) throws NumberFormatException, NoSuchAlgorithmException { EncryptionAlgorithm encrypt = null; OBJECT_IDENTIFIER eccOID = new OBJECT_IDENTIFIER("1.2.840.10045.2.1"); if (encryptOID.equals(eccOID.toString())) { // old CRMFPopClients send this OID for ECC Keys for no apparent reason. // New clients set this correctly. // We'll assume the old DES3 wrapping here. encrypt = EncryptionAlgorithm.DES_CBC_PAD; } else if (encryptOID.equals(KeyWrapAlgorithm.DES3_CBC_PAD_OID.toString())) { encrypt = EncryptionAlgorithm.DES3_CBC_PAD; } else if (encryptOID.equals(KeyWrapAlgorithm.AES_CBC_PAD_OID.toString())) { encrypt = EncryptionAlgorithm.AES_128_CBC_PAD; } else { encrypt = EncryptionAlgorithm.fromOID(new OBJECT_IDENTIFIER(encryptOID)); } KeyWrapAlgorithm wrap = null; if (wrapName != null) { wrap = KeyWrapAlgorithm.fromString(wrapName); payloadWrapAlgorithm = wrap; } switch (encrypt.getAlg().toString()) { case "AES": // TODO(alee) - Terrible hack till we figure out why GCM is not working // or a way to detect the padding. // We are going to assume AES-128-PAD encrypt = EncryptionAlgorithm.AES_128_CBC_PAD; skType = SymmetricKey.AES; skKeyGenAlgorithm = KeyGenAlgorithm.AES; if (wrap == null) payloadWrapAlgorithm = KeyWrapAlgorithm.AES_KEY_WRAP_PAD; break; case "DESede": skType = SymmetricKey.DES3; skKeyGenAlgorithm = KeyGenAlgorithm.DES3; skWrapAlgorithm = KeyWrapAlgorithm.DES3_CBC_PAD; if (wrap == null) payloadWrapAlgorithm = KeyWrapAlgorithm.DES3_CBC_PAD; break; case "DES": skType = SymmetricKey.DES; skKeyGenAlgorithm = KeyGenAlgorithm.DES; skWrapAlgorithm = KeyWrapAlgorithm.DES3_CBC_PAD; if (wrap == null) payloadWrapAlgorithm = KeyWrapAlgorithm.DES_CBC_PAD; break; default: throw new NoSuchAlgorithmException("Invalid algorithm"); } this.skLength = encrypt.getKeyStrength(); if (priKeyAlgo.equals("EC")) { skWrapAlgorithm = KeyWrapAlgorithm.AES_ECB; } else { skWrapAlgorithm = KeyWrapAlgorithm.RSA; } payloadEncryptionAlgorithm = encrypt; payloadEncryptionIV = encryptIV; if (payloadWrapAlgorithm == KeyWrapAlgorithm.AES_KEY_WRAP_PAD) { // TODO(alee) Hack -- if we pass in null for the iv in the // PKIArchiveOptions, we fail to decode correctly when parsing a // CRMFPopClient request. payloadWrappingIV = null; } else { payloadWrappingIV = wrapIV; } } private WrappingParams(String wrapOID, String priKeyAlgo, IVParameterSpec wrapIV) throws NumberFormatException, NoSuchAlgorithmException { KeyWrapAlgorithm kwAlg = KeyWrapAlgorithm.fromOID(wrapOID); if (kwAlg == KeyWrapAlgorithm.AES_KEY_WRAP_PAD) { skType = SymmetricKey.AES; skKeyGenAlgorithm = KeyGenAlgorithm.AES; payloadWrapAlgorithm = KeyWrapAlgorithm.AES_KEY_WRAP_PAD; payloadEncryptionAlgorithm = EncryptionAlgorithm.AES_128_CBC_PAD; skLength = 128; } else if (kwAlg == KeyWrapAlgorithm.AES_CBC_PAD) { skType = SymmetricKey.AES; skKeyGenAlgorithm = KeyGenAlgorithm.AES; payloadWrapAlgorithm = KeyWrapAlgorithm.AES_CBC_PAD; payloadEncryptionAlgorithm = EncryptionAlgorithm.AES_128_CBC_PAD; skLength = 128; } else if (kwAlg == KeyWrapAlgorithm.DES3_CBC_PAD) { skType = SymmetricKey.DES3; skKeyGenAlgorithm = KeyGenAlgorithm.DES3; skWrapAlgorithm = KeyWrapAlgorithm.DES3_CBC_PAD; payloadWrapAlgorithm = KeyWrapAlgorithm.DES3_CBC_PAD; payloadEncryptionAlgorithm = EncryptionAlgorithm.DES3_CBC_PAD; skLength = payloadEncryptionAlgorithm.getKeyStrength(); } else if (kwAlg == KeyWrapAlgorithm.DES_CBC_PAD) { skType = SymmetricKey.DES; skKeyGenAlgorithm = KeyGenAlgorithm.DES; skWrapAlgorithm = KeyWrapAlgorithm.DES3_CBC_PAD; payloadWrapAlgorithm = KeyWrapAlgorithm.DES3_CBC_PAD; payloadEncryptionAlgorithm = EncryptionAlgorithm.DES_CBC_PAD; skLength = payloadEncryptionAlgorithm.getKeyStrength(); } if (priKeyAlgo.equals("EC")) { skWrapAlgorithm = KeyWrapAlgorithm.AES_ECB; } else { skWrapAlgorithm = KeyWrapAlgorithm.RSA; } // set the IVs payloadEncryptionIV = wrapIV; if (payloadWrapAlgorithm == KeyWrapAlgorithm.AES_KEY_WRAP_PAD) { // TODO(alee) Hack -- if we pass in null for the iv in the // PKIArchiveOptions, we fail to decode correctly when parsing a // CRMFPopClient request. payloadWrappingIV = null; } else { payloadWrappingIV = wrapIV; } } public static WrappingParams getWrappingParamsFromArchiveOptions(String wrapOID, String priKeyAlgo, IVParameterSpec wrapIV) throws NumberFormatException, NoSuchAlgorithmException { return new WrappingParams(wrapOID, priKeyAlgo, wrapIV); } public SymmetricKey.Type getSkType() { return skType; } public void setSkType(SymmetricKey.Type skType) { this.skType = skType; } public void setSkType(String skTypeName) throws NoSuchAlgorithmException { this.skType = SymmetricKey.Type.fromName(skTypeName); } public KeyGenAlgorithm getSkKeyGenAlgorithm() { return skKeyGenAlgorithm; } public void setSkKeyGenAlgorithm(KeyGenAlgorithm skKeyGenAlgorithm) { this.skKeyGenAlgorithm = skKeyGenAlgorithm; } public void setSkKeyGenAlgorithm(String algName) throws NoSuchAlgorithmException { // JSS mapping is not working. Lets just do something brain-dead to // handle the cases we expect. if (algName.equalsIgnoreCase("AES")) { skKeyGenAlgorithm = KeyGenAlgorithm.AES; } else if (algName.equalsIgnoreCase("DES")) { skKeyGenAlgorithm = KeyGenAlgorithm.DES; } else if (algName.equalsIgnoreCase("DESede")) { skKeyGenAlgorithm = KeyGenAlgorithm.DES3; } else if (algName.equalsIgnoreCase("DES3")) { skKeyGenAlgorithm = KeyGenAlgorithm.DES3; } } public int getSkLength() { return skLength; } public void setSkLength(int skLength) { this.skLength = skLength; } public KeyWrapAlgorithm getSkWrapAlgorithm() { return skWrapAlgorithm; } public void setSkWrapAlgorithm(KeyWrapAlgorithm skWrapAlgorithm) { this.skWrapAlgorithm = skWrapAlgorithm; } public void setSkWrapAlgorithm(String name) throws NoSuchAlgorithmException { this.skWrapAlgorithm = KeyWrapAlgorithm.fromString(name); } public EncryptionAlgorithm getPayloadEncryptionAlgorithm() { return payloadEncryptionAlgorithm; } public void setPayloadEncryptionAlgorithm(EncryptionAlgorithm payloadEncryptionAlgorithm) { this.payloadEncryptionAlgorithm = payloadEncryptionAlgorithm; } public void setPayloadEncryptionAlgorithm(String algName, String modeName, String paddingName, int keyStrength) throws NoSuchAlgorithmException { this.payloadEncryptionAlgorithm = EncryptionAlgorithm.lookup(algName, modeName, paddingName, keyStrength); } public String getPayloadEncryptionAlgorithmName() { // work around some of the issues with OIDs in JSS int strength = payloadEncryptionAlgorithm.getKeyStrength(); String mode = payloadEncryptionAlgorithm.getMode().toString(); String padding = payloadEncryptionAlgorithm.getPadding().toString(); String alg = payloadEncryptionAlgorithm.getAlg().toString(); return alg + "/" + mode + "/" + padding + "/" + Integer.toString(strength); } public KeyWrapAlgorithm getPayloadWrapAlgorithm() { return payloadWrapAlgorithm; } public void setPayloadWrapAlgorithm(KeyWrapAlgorithm payloadWrapAlgorithm) { this.payloadWrapAlgorithm = payloadWrapAlgorithm; } public void setPayloadWrapAlgorithm(String name) throws NoSuchAlgorithmException { this.payloadWrapAlgorithm = KeyWrapAlgorithm.fromString(name); } public IVParameterSpec getPayloadEncryptionIV() { return payloadEncryptionIV; } public void setPayloadEncryptionIV(IVParameterSpec payloadEncryptionIV) { this.payloadEncryptionIV = payloadEncryptionIV; } public IVParameterSpec getPayloadWrappingIV() { return payloadWrappingIV; } public void setPayloadWrappingIV(IVParameterSpec payloadWrappingIV) { this.payloadWrappingIV = payloadWrappingIV; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/000077500000000000000000000000001412550063600241645ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/ACertAttrSet.java000066400000000000000000000106541412550063600273420ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Enumeration; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * A plain certattr set used by pkcs10 to parse an unknown attribute. * * @author Lily Hsiao */ public class ACertAttrSet implements CertAttrSet { protected DerValue mDerValue = null; public ACertAttrSet(DerValue derValue) throws IOException { mDerValue = derValue; } public DerValue getDerValue() { return mDerValue; } /** * Returns a short string describing this certificate attribute. * * @return value of this certificate attribute in * printable form. */ @Override public String toString() { return "ACertAttrSet value " + (mDerValue == null ? "null" : "not null"); } /** * Encodes the attribute to the output stream in a format * that can be parsed by the decode method. * * @param out the OutputStream to encode the attribute to. * * @exception CertificateException on encoding or validity errors. * @exception IOException on other errors. */ @Override public void encode(OutputStream out) throws CertificateException, IOException { mDerValue.encode((DerOutputStream) out); } /** * Decodes the attribute in the input stream. * * @param in the InputStream to read the encoded attribute from. * * @exception CertificateException on decoding or validity errors. * @exception IOException on other errors. */ @Override public void decode(InputStream in) throws CertificateException, IOException { throw new IOException("not supported"); } /** * Sets an attribute value within this CertAttrSet. * * @param name the name of the attribute (e.g. "x509.info.key") * @param obj the attribute object. * * @exception CertificateException on attribute handling errors. * @exception IOException on other errors. */ @Override public void set(String name, Object obj) throws CertificateException, IOException { throw new IOException("not supported"); } /** * Gets an attribute value for this CertAttrSet. * * @param name the name of the attribute to return. * * @exception CertificateException on attribute handling errors. * @exception IOException on other errors. */ @Override public Object get(String name) throws CertificateException, IOException { throw new IOException("not supported"); } /** * Deletes an attribute value from this CertAttrSet. * * @param name the name of the attribute to delete. * * @exception CertificateException on attribute handling errors. * @exception IOException on other errors. */ @Override public void delete(String name) throws CertificateException, IOException { throw new IOException("not supported"); } /** * Returns an enumeration of the names of the attributes existing within * this attribute. * * @return an enumeration of the attribute names. */ @Override public Enumeration getAttributeNames() { return null; } /** * Returns the name (identifier) of this CertAttrSet. * * @return the name of this CertAttrSet. */ @Override public String getName() { return "Generic Extension"; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/AVA.java000066400000000000000000000236401412550063600254430ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.UnsupportedCharsetException; import org.mozilla.jss.netscape.security.util.DerEncoder; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** * X.500 Attribute-Value-Assertion (AVA): an attribute, as identified by * some attribute ID, has some particular value. Values are as a rule ASN.1 * printable strings. A conventional set of type IDs is recognized when * parsing (and generating) RFC 1779 syntax strings. * *

* AVAs are components of X.500 relative names. Think of them as being individual fields of a database record. The * attribute ID is how you identify the field, and the value is part of a particular record. * * @see X500Name * @see RDN * @see LdapDNStrConverter * * @version 1.14 * * @author David Brownell * @author Amit Kapoor * @author Hemma Prafullchandra */ // public ... when RDN is public and X.500Names can be // constructed using RDNs, and all three classes are cleaner public final class AVA implements DerEncoder { ObjectIdentifier oid; DerValue value; /** * Constructs an AVA from a Ldap DN string with one AVA component * using the global default LdapDNStrConverter. * * @see LdapDNStrConverter * @param avaString a Ldap DN string with one AVA component. */ public AVA(String avaString) throws IOException { AVA ava; ava = LdapDNStrConverter.getDefault().parseAVA(avaString); oid = ava.getOid(); value = ava.getValue(); } /** * Like AVA(String) with a DER encoding order given for Directory Strings. */ public AVA(String avaString, byte[] tags) throws IOException { AVA ava; ava = LdapDNStrConverter.getDefault().parseAVA(avaString, tags); oid = ava.getOid(); value = ava.getValue(); } /** * Constructs an AVA from a Ldap DN string containing one AVA * component using the specified LdapDNStrConverter. * * @see LdapDNStrConverter * @param avaString a Ldap DN string containing one AVA. * @param ldapDNStrConverter a LdapDNStrConverter */ public AVA(String avaString, LdapDNStrConverter ldapDNStrConverter) throws IOException { AVA ava; ava = ldapDNStrConverter.parseAVA(avaString); oid = ava.getOid(); value = ava.getValue(); } /** * Constructs an AVA from an OID and DerValue. * * @param type an ObjectIdentifier * @param val a DerValue */ public AVA(ObjectIdentifier type, DerValue val) throws IOException { oid = type; value = val; } /** * Constructs an AVA from an input stream of UTF8 bytes that form * a Ldap DN string. Then parse the Ldap DN string using the global * default LdapDNStrConverter.
* Parses an RFC 1779 style AVA string: CN=fee fie foe fum * or perhaps with quotes. Not all defined AVA tags are supported; * of current note are X.400 related ones (PRMD, ADMD, etc). * * This terminates at unescaped AVA separators ("+") or RDN * separators (",", ";"), or DN terminators {@literal (">")}, and removes * cosmetic whitespace at the end of values. * * @see LdapDNStrConverter * @param in the input stream. */ public AVA(InputStream in) throws IOException { try { // convert from UTF8 bytes to java string then parse it. byte[] buffer = new byte[in.available()]; in.read(buffer); Charset charset = Charset.forName("UTF-8"); CharsetDecoder decoder = charset.newDecoder(); CharBuffer charBuffer = decoder.decode(ByteBuffer.wrap(buffer)); AVA a = LdapDNStrConverter.getDefault().parseAVA(charBuffer.toString()); oid = a.getOid(); value = a.getValue(); } catch (UnsupportedCharsetException e) { throw new IOException("UTF8 encoding not supported", e); } } /** * Constructs an AVA from a Der Input Stream. * * @param in the Der Input Stream. */ public AVA(DerInputStream in) throws IOException { DerValue assertion = in.getDerValue(); /* * Individual attribute value assertions are SEQUENCE of two values. * That'd be a "struct" outside of ASN.1. */ if (assertion.tag != DerValue.tag_Sequence) throw new CertParseError("X500 AVA, not a sequence"); ObjectIdentifier o = assertion.data.getOID(); oid = X500NameAttrMap.getDefault().getOid(o); if (oid == null) { // NSCP #329837 // if this OID is not recongized in our map (table), // it is fine. we just store it as regular OID. oid = o; } value = assertion.data.getDerValue(); if (assertion.data.available() != 0) throw new CertParseError("AVA, extra bytes = " + assertion.data.available()); } // other public methods. /** * Returns true if another AVA has the same OID and DerValue. * * @param other the other AVA. * @return ture iff other AVA has same oid and value. */ public boolean equals(AVA other) { return oid.equals(other.oid) && value.equals(other.value); } /** * Compares the AVA with an Object, returns true if the object is * an AVA and has the same OID and value. * * @param other the other object. * @return true iff other object is an AVA and has same oid and value. */ @Override public boolean equals(Object other) { if (other instanceof AVA) return equals((AVA) other); else return false; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((oid == null) ? 0 : oid.hashCode()); result = prime * result + ((value == null) ? 0 : value.hashCode()); return result; } /** * Encodes the AVA to a Der output stream. * AVAs are encoded as a SEQUENCE of two elements. * * @param out The Der output stream. */ public void encode(DerOutputStream out) throws IOException { derEncode(out); } /** * DER encode this object onto an output stream. * Implements the DerEncoder interface. * * @param out * the output stream on which to write the DER encoding. * * @exception IOException on encoding error. */ @Override public void derEncode(OutputStream out) throws IOException { try (DerOutputStream tmp2 = new DerOutputStream()) { DerOutputStream tmp = new DerOutputStream(); tmp.putOID(oid); value.encode(tmp); tmp2.write(DerValue.tag_Sequence, tmp); out.write(tmp2.toByteArray()); } } /** * Returns a Ldap DN string with one AVA component using * the global default LdapDNStrConverter. * * @return a Ldap DN string * @exception IOException if an error occurs during conversion. * @see LdapDNStrConverter */ public String toLdapDNString() throws IOException { LdapDNStrConverter v = LdapDNStrConverter.getDefault(); return v.encodeAVA(this); } /** * Returns a Ldap DN string with one AVA component using the specified * LdapDNStrConverter. * * @return a Ldap DN string * @param ldapDNStrConverter a Ldap DN String Converter * @exception IOException if an error occurs during the conversion. * @see LdapDNStrConverter */ public String toLdapDNString(LdapDNStrConverter ldapDNStrConverter) throws IOException { return ldapDNStrConverter.encodeAVA(this); } /** * Returns a Ldap DN string with the AVA component using the global * default LdapDNStrConverter, or null if an error occurs in conversion. * * @return a Ldap DN string containing the AVA, or null if an * error occurs in the conversion. */ @Override public String toString() { String s; try { // NOTE that a LdapDNString is returned here to match the // original source from sun. Could also return the raw value // (before Ldap escaping) here. s = toLdapDNString(); } catch (IOException e) { return null; } return s; } /** * Returns the OID in the AVA. * * @return the ObjectIdentifier in this AVA. */ public ObjectIdentifier getOid() { return oid; } /** * Returns the value in this AVA as a DerValue * * @return attribute value in this AVA. */ public DerValue getValue() { return value; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/AVAValueConverter.java000066400000000000000000000061751412550063600303340ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import org.mozilla.jss.netscape.security.util.DerValue; /** * Interface for classes that convert a attribute value string to a * DER encoded ASN.1 value and vice versa. * The converters are associated with attribute types, such as * directory string, ia5string, etc. * *

* For example, to convert a string, such as an organization name for the "O" attribute to a DerValue, the "O" attribute * is mapped to the DirStrConverter which is used to convert the organization name to a DER encoded Directory String * which is a DerValue of a ASN.1 PrintableString, T.61String or UniversalString for the organization name. * * @author Lily Hsiao, Slava Galperin at Netscape Communications, Inc. */ public interface AVAValueConverter { /** * Converts a string to a DER encoded attribute value. * * @param valueString An AVA value string not encoded in any form. * * @return A DerValue object. * * @exception IOException if an error occurs during the conversion. */ public DerValue getValue(String valueString) throws IOException; /** * Converts a string to a DER encoded attribute value. * Specify the order of DER tags to use if more than one encoding is * possible. Currently Directory Strings can have different order * for backwards compatibility. By 2003 all should be UTF8String. * * @param valueString An AVA value string not encoded in any form. * * @return A DerValue object. * * @exception IOException if an error occurs during the conversion. */ public DerValue getValue(String valueString, byte[] tags) throws IOException; /** * Converts a BER encoded value to a DER encoded attribute value. * * @param berStream A byte array of the BER encoded AVA value. * @return A DerValue object. */ public DerValue getValue(byte[] berStream) throws IOException; /** * Converts a DER encoded value to a string, not encoded in any form. * * @param avaValue A DerValue object. * * @return A string for the value or null if it can't be converted. * * @exception IOException if an error occurs during the conversion. */ public String getAsString(DerValue avaValue) throws IOException; } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/AlgIdDSA.java000066400000000000000000000152621412550063600263450ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.math.BigInteger; import java.security.ProviderException; import java.security.interfaces.DSAParams; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class identifies DSS/DSA Algorithm variants, which are distinguished * by using different algorithm parameters P, Q, G. It uses the * NIST/IETF standard DER encoding. These are used to implement the Digital * Signature Standard (DSS), FIPS 186. * *

* NOTE: At this time, DSS/DSA Algorithm IDs must always * include these parameters. Use of DSS/DSA in modes where parameters are * either implicit (e.g. a default applicable to a site or a larger scope), * or are derived from some Certificate Authority's DSS certificate, is * not currently supported. * * @version 1.31 * @author David Brownell */ public final class AlgIdDSA extends AlgorithmId implements DSAParams { /** * */ private static final long serialVersionUID = 5978220691806461631L; /* * The three unsigned integer parameters. */ private BigInteger p, q, g; /** Returns the DSS/DSA parameter "P" */ @Override public BigInteger getP() { return p; } /** Returns the DSS/DSA parameter "Q" */ @Override public BigInteger getQ() { return q; } /** Returns the DSS/DSA parameter "G" */ @Override public BigInteger getG() { return g; } AlgIdDSA(DerValue val) throws IOException { super(val.getOID()); } /** * Construct an AlgIdDSA from an X.509 encoded byte array. */ public AlgIdDSA(byte[] encodedAlg) throws IOException { super(new DerValue(encodedAlg).getOID()); } /** * Constructs a DSS/DSA Algorithm ID from unsigned integers that * define the algorithm parameters. Those integers are encoded * as big-endian byte arrays. * * @param p the DSS/DSA paramter "P" * @param q the DSS/DSA paramter "Q" * @param g the DSS/DSA paramter "G" */ public AlgIdDSA(byte p[], byte q[], byte g[]) throws IOException { this(new BigInteger(1, p), new BigInteger(1, q), new BigInteger(1, g)); } /** * Constructs a DSS/DSA Algorithm ID from numeric parameters. * * @param p the DSS/DSA paramter "P" * @param q the DSS/DSA paramter "Q" * @param g the DSS/DSA paramter "G" */ public AlgIdDSA(BigInteger p, BigInteger q, BigInteger g) { super(DSA_oid); try { this.p = p; this.q = q; this.g = g; initializeParams(); } catch (IOException e) { /* this should not happen */ throw new ProviderException("Construct DSS/DSA Algorithm ID"); } } /** * Returns "DSA", indicating the Digital Signature Algorithm (DSA) as * defined by the Digital Signature Standard (DSS), FIPS 186. */ @Override public String getName() { return "DSA"; } /* * For algorithm IDs which haven't been created from a DER encoded * value, "params" must be created. */ private void initializeParams() throws IOException { try (DerOutputStream out = new DerOutputStream()) { out.putInteger(new BigInt(p.toByteArray())); out.putInteger(new BigInt(q.toByteArray())); out.putInteger(new BigInt(g.toByteArray())); params = new DerValue(DerValue.tag_Sequence, out.toByteArray()); } } /** * Parses algorithm parameters P, Q, and G. They're found * in the "params" member, which never needs to be changed. */ @Override protected void decodeParams() throws IOException { if (params == null || params.tag != DerValue.tag_Sequence) throw new IOException("DSA alg parsing error"); params.data.reset(); this.p = params.data.getInteger().toBigInteger(); this.q = params.data.getInteger().toBigInteger(); this.g = params.data.getInteger().toBigInteger(); if (params.data.available() != 0) throw new IOException("AlgIdDSA params, extra=" + params.data.available()); } /* * Returns a formatted string describing the parameters. */ @Override public String toString() { return paramsToString(); } /* * Returns a string describing the parameters. */ @Override protected String paramsToString() { return "\n p:\n" + (new BigInt(p)).toString() + "\n q:\n" + (new BigInt(q)).toString() + "\n g:\n" + (new BigInt(g)).toString() + "\n"; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((g == null) ? 0 : g.hashCode()); result = prime * result + ((p == null) ? 0 : p.hashCode()); result = prime * result + ((q == null) ? 0 : q.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; AlgIdDSA other = (AlgIdDSA) obj; if (g == null) { if (other.g != null) return false; } else if (!g.equals(other.g)) return false; if (p == null) { if (other.p != null) return false; } else if (!p.equals(other.p)) return false; if (q == null) { if (other.q != null) return false; } else if (!q.equals(other.q)) return false; return true; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/AlgorithmId.java000066400000000000000000001154721412550063600272440ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.OutputStream; import java.io.Serializable; import java.lang.IllegalArgumentException; import java.security.AlgorithmParameters; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.spec.InvalidParameterSpecException; import java.security.spec.MGF1ParameterSpec; import java.security.spec.PSSParameterSpec; import org.mozilla.jss.netscape.security.util.DerEncoder; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** * This class identifies algorithms, such as cryptographic transforms, each * of which may be associated with parameters. Instances of this base class * are used when this runtime environment has no special knowledge of the * algorithm type, and may also be used in other cases. Equivalence is * defined according to OID and (where relevant) parameters. * *

* Subclasses may be used, for example when when the algorithm ID has associated parameters which some code (e.g. code * using public keys) needs to have parsed. Two examples of such algorithms are Diffie-Hellman key exchange, and the * Digital Signature Standard Algorithm (DSS/DSA). * *

* The OID constants defined in this class correspond to some widely used algorithms, for which conventional string * names have been defined. This class is not a general repository for OIDs, or for such string names. Note that the * mappings between algorithm IDs and algorithm names is not one-to-one. * * @version 1.70 * * @author David Brownell * @author Amit Kapoor * @author Hemma Prafullchandra */ public class AlgorithmId implements Serializable, DerEncoder { /** use serialVersionUID from JDK 1.1. for interoperability */ private static final long serialVersionUID = 7205873507486557157L; /** * The object identitifer being used for this algorithm. */ private ObjectIdentifier algid = null; // The (parsed) parameters private AlgorithmParameters algParams = null; // Use this for the various flavors of the RSA PSS alg. private String cachedAlgName = null; /** * Parameters for this algorithm. These are stored in unparsed * DER-encoded form; subclasses can be made to automaticaly parse * them so there is fast access to these parameters. */ protected DerValue params = null; protected String paramsString = null; public AlgorithmParameters getParameters() { return this.algParams; } public String getParametersString() { return this.paramsString; } public void setParametersString(String paramStr) { this.paramsString = paramStr; } /** * Returns one of the algorithm IDs most commonly associated * with this algorithm name. * * @param algname the name being used * @exception NoSuchAlgorithmException on error. */ public static AlgorithmId get(String algname) throws NoSuchAlgorithmException { ObjectIdentifier oid = algOID(algname); if (oid == null) throw new NoSuchAlgorithmException("unrecognized algorithm name: " + algname); try { return new AlgorithmId(oid, algname); } catch (Exception e) { throw new NoSuchAlgorithmException(e); } } /** * Parse (unmarshal) an ID from a DER sequence input value. This form * parsing might be used when expanding a value which has already been * partially unmarshaled as a set or sequence member. * * @exception IOException on error. * @param val the input value, which contains the algid and, if * there are any parameters, those parameters. * @return an ID for the algorithm. If the system is configured * appropriately, this may be an instance of a class * with some kind of special support for this algorithm. * In that case, you may "narrow" the type of the ID. */ public static AlgorithmId parse(DerValue val) throws IOException { if (val.tag != DerValue.tag_Sequence) throw new IOException("algid parse error, not a sequence"); /* * Get the algorithm ID and any parameters. */ ObjectIdentifier algid; DerValue params; DerInputStream in = val.toDerInputStream(); algid = in.getOID(); if (in.available() == 0) params = null; else { params = in.getDerValue(); if (params.tag == DerValue.tag_Null) params = null; } /* * Figure out what class (if any) knows about this oid's * parameters. Make one, and give it the data to decode. */ AlgorithmId alg = null; // omit parameter field for ECDSA if (!algid.equals(sha224WithEC_oid) && !algid.equals(sha256WithEC_oid) && !algid.equals(sha384WithEC_oid) && !algid.equals(sha512WithEC_oid)) { alg = new AlgorithmId(algid, params); } else { try { alg = new AlgorithmId(algid); } catch (Exception e) { throw new IOException(e); } } if (params != null) alg.decodeParams(); /* * Set the raw params string in case * higher level code might want the info */ String paramStr = null; if (params != null) { paramStr = params.toString(); } alg.setParametersString(paramStr); return alg; } public static AlgorithmId parse(byte[] val) throws IOException { return null; } /** * Constructs an algorithm ID with a fully encoded params object * @param oid the identifier for the algorithm * @param params the fully encoded AlgorithmIdentifier Object * @throws NoSuchAlgorithmException * @throws IOException */ public AlgorithmId(ObjectIdentifier oid, AlgorithmParameters params) throws IOException, NoSuchAlgorithmException { algid = oid; algParams = params; if (algParams == null) { throw new NoSuchAlgorithmException("AlgorithmId: null algParams."); } this.params = new DerValue(algParams.getEncoded()); } /** * Constructor that takes the oid and name, so the name can be cachedf or laster use. * @throws NoSuchAlgorithmException * @throws IOException * */ public AlgorithmId(ObjectIdentifier oid, String algName) throws IOException, NoSuchAlgorithmException { algid = oid; cachedAlgName = algName; /* Create the params if our algorithm is RSA PSS related */ if (algName != null && algName.contains("PSS")) { this.algParams = getPSSParams(algName); this.params = new DerValue(this.algParams.getEncoded()); } } /** * Constructs an algorithm ID with possible RSAPSS params. * * @param oid the identifier for the algorithm */ public AlgorithmId(ObjectIdentifier oid) { algid = oid; String algName = algName(); /* Create the params if our algorithm is RSA PSS related */ if (algName != null && algName.contains("PSS")) { try { this.algParams = getPSSParams(algName); if (this.algParams != null) { try { this.params = new DerValue(this.algParams.getEncoded()); } catch (IOException e) { throw new IOException(e); } } } catch (Exception e) { //Preserve original signature... throw new RuntimeException("Unable to create pssPrams in Algorithmid(ObjectIdentifier oid): " + e.getMessage(), e); } } } private AlgorithmParameters getPSSParams(String algName) throws NoSuchAlgorithmException, IOException { cachedAlgName = algName; AlgorithmParameters ret = null; /* Create the params if our algorithm is RSA PSS related */ try { ret = createPSSAlgorithmParameters(algName); } catch (Exception e) { throw new NoSuchAlgorithmException(e); } return ret; } private AlgorithmId(ObjectIdentifier oid, DerValue params) throws IOException { this.algid = oid; this.params = params; if (this.params != null) decodeParams(); } /** * Constructs an algorithm ID which will be initialized * separately, for example by deserialization. * * @deprecated use one of the other constructors. */ @Deprecated public AlgorithmId() { } protected void decodeParams() throws IOException { try { if (algid.equals(AlgorithmId.rsaPSS_oid)) { try { this.algParams = createPSSAlgorithmParametersFromData(this.params.toByteArray()); return; } catch (Exception e) { throw new IOException(e); } } else { this.algParams = AlgorithmParameters.getInstance(this.algid.toString()); } } catch (NoSuchAlgorithmException e) { /* * This algorithm parameter type is not supported, so we cannot * parse the parameters. */ this.algParams = null; return; } // Decode (parse) the parameters this.algParams.init(this.params.toByteArray()); } /** * Marshal a DER-encoded "AlgorithmID" sequence on the DER stream. */ public final void encode(DerOutputStream out) throws IOException { derEncode(out); } /** * DER encode this object onto an output stream. * Implements the DerEncoder interface. * @param out the output stream on which to write the DER encoding. * * @exception IOException on encoding error. */ @Override public void derEncode(OutputStream out) throws IOException { try (DerOutputStream tmp = new DerOutputStream()) { DerOutputStream bytes = new DerOutputStream(); bytes.putOID(algid); // omit parameter field for ECDSA if (!algid.equals(sha224WithEC_oid) && !algid.equals(sha256WithEC_oid) && !algid.equals(sha384WithEC_oid) && !algid.equals(sha512WithEC_oid)) { if (params == null) { bytes.putNull(); } else bytes.putDerValue(params); } tmp.write(DerValue.tag_Sequence, bytes); out.write(tmp.toByteArray()); } } /** * DER encode this object onto an output stream. * Implements the DerEncoder interface. * * @param out the output stream on which to write the DER encoding params, * using context value. * * @exception IOException on encoding error. */ public void derEncodeWithContext(OutputStream out, int contextVal) throws IOException { try (DerOutputStream tmp = new DerOutputStream()) { DerOutputStream bytes = new DerOutputStream(); bytes.putOID(algid); byte val = (byte) contextVal; // omit parameter field for ECDSA if (!algid.equals(sha224WithEC_oid) && !algid.equals(sha256WithEC_oid) && !algid.equals(sha384WithEC_oid) && !algid.equals(sha512WithEC_oid)) { if (params == null) { bytes.putNull(); } else { bytes.putDerValue(params); } } DerOutputStream seq = new DerOutputStream(); seq.write(DerValue.tag_Sequence, bytes); tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, val), seq); out.write(tmp.toByteArray()); } } // XXXX cleaning required /** * Returns the DER-encoded X.509 AlgorithmId as a byte array. */ public final byte[] encode() throws IOException { try (DerOutputStream out = new DerOutputStream()) { DerOutputStream bytes = new DerOutputStream(); bytes.putOID(algid); // omit parameter field for ECDSA if (!algid.equals(sha224WithEC_oid) && !algid.equals(sha256WithEC_oid) && !algid.equals(sha384WithEC_oid) && !algid.equals(sha512WithEC_oid)) { if (params == null) { bytes.putNull(); } else bytes.putDerValue(params); } out.write(DerValue.tag_Sequence, bytes); return out.toByteArray(); } } /** * Returns list of signing algorithms for a key algorithm such as * RSA or DSA. */ public static String[] getSigningAlgorithms(AlgorithmId alg) { ObjectIdentifier algOid = alg.getOID(); if (algOid.equals(DSA_oid) || algOid.equals(DSA_OIW_oid)) { return DSA_SIGNING_ALGORITHMS; } else if (algOid.equals(RSA_oid) || algOid.equals(RSAEncryption_oid)) { return RSA_SIGNING_ALGORITHMS; } else if (algOid.equals(ANSIX962_EC_Public_Key_oid) || algOid.equals(ANSIX962_SHA1_With_EC_oid)) { return EC_SIGNING_ALGORITHMS; } else { return null; } } /* * Translates from some common algorithm names to the * OID with which they're usually associated ... this mapping * is the reverse of the one below, except in those cases * where synonyms are supported or where a given algorithm * is commonly associated with multiple OIDs. */ private static ObjectIdentifier algOID(String name) { // Digesting algorithms if (name.equals("MD5")) return AlgorithmId.MD5_oid; if (name.equals("MD2")) return AlgorithmId.MD2_oid; if (name.equals("SHA") || name.equals("SHA1") || name.equals("SHA-1")) return AlgorithmId.SHA_oid; if (name.equals("SHA256") || name.equals("SHA-256")) return AlgorithmId.SHA256_oid; if (name.equals("SHA512") || name.equals("SHA-512")) return AlgorithmId.SHA512_oid; // Various public key algorithms if (name.equals("RSA")) return AlgorithmId.RSA_oid; if (name.equals("RSAEncryption")) return AlgorithmId.RSAEncryption_oid; if (name.equals("Diffie-Hellman") || name.equals("DH")) return AlgorithmId.DH_oid; if (name.equals("DSA")) return AlgorithmId.DSA_oid; // Common signature types if (name.equals("SHA1withEC") || name.equals("SHA1/EC") || name.equals("1.2.840.10045.4.1")) return AlgorithmId.sha1WithEC_oid; if (name.equals("SHA224withEC") || name.equals("SHA224/EC") || name.equals("1.2.840.10045.4.3.1")) return AlgorithmId.sha224WithEC_oid; if (name.equals("SHA256withEC") || name.equals("SHA256/EC") || name.equals("1.2.840.10045.4.3.2")) return AlgorithmId.sha256WithEC_oid; if (name.equals("SHA384withEC") || name.equals("SHA384/EC") || name.equals("1.2.840.10045.4.3.3")) return AlgorithmId.sha384WithEC_oid; if (name.equals("SHA512withEC") || name.equals("SHA512/EC") || name.equals("1.2.840.10045.4.3.4")) return AlgorithmId.sha512WithEC_oid; if (name.equals("SHA1withRSA") || name.equals("SHA1/RSA") || name.equals("1.2.840.113549.1.1.5")) return AlgorithmId.sha1WithRSAEncryption_oid; if (name.equals("SHA256withRSA") || name.equals("SHA256/RSA") || name.equals("1.2.840.113549.1.1.11")) return AlgorithmId.sha256WithRSAEncryption_oid; if (name.equals("SHA384withRSA") || name.equals("SHA384/RSA") || name.equals("1.2.840.113549.1.1.12")) return AlgorithmId.sha384WithRSAEncryption_oid; if (name.equals("SHA512withRSA") || name.equals("SHA512/RSA") || name.equals("1.2.840.113549.1.1.13")) return AlgorithmId.sha512WithRSAEncryption_oid; if (name.equals("MD5withRSA") || name.equals("MD5/RSA")) return AlgorithmId.md5WithRSAEncryption_oid; if (name.equals("MD2withRSA") || name.equals("MD2/RSA")) return AlgorithmId.md2WithRSAEncryption_oid; if (name.equals("SHAwithDSA") || name.equals("SHA1withDSA") || name.equals("SHA/DSA") || name.equals("SHA1/DSA")) return AlgorithmId.sha1WithDSA_oid; if (name.equals("SHA256withRSA/PSS") || name.equals("SHA384withRSA/PSS") || name.equals("SHA512withRSA/PSS")) return AlgorithmId.rsaPSS_oid; return null; } /* * For the inevitable cases where key or signature types are not * configured in an environment which encounters such keys or * signatures, we still attempt to provide user-friendly names * for some of the most common algorithms. Subclasses can of * course override getName(). * * Wherever possible, the names are those defined by the IETF. * Such names are noted below. */ private String algName() { // Common message digest algorithms if (algid.equals(AlgorithmId.MD5_oid)) return "MD5"; // RFC 1423 if (algid.equals(AlgorithmId.MD2_oid)) return "MD2"; // RFC 1423 if (algid.equals(AlgorithmId.SHA_oid)) return "SHA"; if (algid.equals(AlgorithmId.SHA256_oid)) return "SHA256"; if (algid.equals(AlgorithmId.SHA384_oid)) return "SHA384"; if (algid.equals(AlgorithmId.SHA512_oid)) return "SHA512"; if (algid.equals(AlgorithmId.rsaPSS_oid)) { if (cachedAlgName != null) { return cachedAlgName; } // Get alg variant from params info String paramStr = paramsToString(); if (paramStr != null) { if (paramStr.contains("HashAlg: SHA-256")) { cachedAlgName = "SHA256withRSA/PSS"; } else if (paramStr.contains("HashAlg: SHA-384")) { cachedAlgName = "SHA384withRSA/PSS"; } else if (paramStr.contains("HashAlg: SHA-512")) { cachedAlgName = "SHA512withRSA/PSS"; } else { throw new RuntimeException("Unknown or unsupported signature algorithm in PSS parameters: " + paramStr); } } return cachedAlgName; } // Common key types if (algid.equals(AlgorithmId.ANSIX962_EC_Public_Key_oid)) return "EC"; if (algid.equals(AlgorithmId.RSAEncryption_oid) || algid.equals(AlgorithmId.RSA_oid)) return "RSA"; if (algid.equals(AlgorithmId.DH_oid) || algid.equals(AlgorithmId.DH_PKIX_oid)) return "Diffie-Hellman"; if (algid.equals(AlgorithmId.DSA_oid) || algid.equals(AlgorithmId.DSA_OIW_oid)) return "DSA"; // Common signature types if (algid.equals(AlgorithmId.sha1WithEC_oid)) return "SHA1withEC"; if (algid.equals(AlgorithmId.sha256WithEC_oid)) return "SHA256withEC"; if (algid.equals(AlgorithmId.sha384WithEC_oid)) return "SHA384withEC"; if (algid.equals(AlgorithmId.sha512WithEC_oid)) return "SHA512withEC"; if (algid.equals(AlgorithmId.md5WithRSAEncryption_oid)) return "MD5withRSA"; if (algid.equals(AlgorithmId.md2WithRSAEncryption_oid)) return "MD2withRSA"; if (algid.equals(AlgorithmId.sha1WithRSAEncryption_oid)) return "SHA1withRSA"; if (algid.equals(AlgorithmId.sha256WithRSAEncryption_oid)) return "SHA256withRSA"; if (algid.equals(AlgorithmId.sha384WithRSAEncryption_oid)) return "SHA384withRSA"; if (algid.equals(AlgorithmId.sha512WithRSAEncryption_oid)) return "SHA512withRSA"; if (algid.equals(AlgorithmId.sha1WithDSA_oid) || algid.equals(AlgorithmId.sha1WithDSA_OIW_oid) || algid.equals(AlgorithmId.shaWithDSA_OIW_oid)) return "SHA1withDSA"; // default returns a dot-notation ID return "OID." + algid.toString(); } /** * Returns the ISO OID for this algorithm. This is usually converted * to a string and used as part of an algorithm name, for example * "OID.1.3.14.3.2.13" style notation. Use the getName call when you do not need to ensure cross-system * portability * of algorithm names, or need a user friendly name. */ final public ObjectIdentifier getOID() { return algid; } /** * Returns a name for the algorithm which may be more intelligible * to humans than the algorithm's OID, but which won't necessarily * be comprehensible on other systems. For example, this might * return a name such as "MD5withRSA" for a signature algorithm on * some systems. It also returns names like "OID.1.2.3.4", when * no particular name for the algorithm is known. */ public String getName() { return algName(); } /** * Returns a string describing only the algorithm without parameters. * * Use toStringWithParams() for algorithm name and paramaters, or * paramsToString() for just parameters. */ @Override public String toString() { return algName(); } /** * Returns a string describing the algorithm and its parameters. */ public String toStringWithParams() { if (params == null) { return algName(); } return algName() + " " + paramsToString(); } /** * Returns the DER encoded parameter, which can then be * used to initialize java.security.AlgorithmParamters. * * @return DER encoded parameters, or null not present. */ public byte[] getEncodedParams() throws IOException { if (params == null) return null; else return params.toByteArray(); } /** * Provides a human-readable description of the algorithm parameters. * This may be redefined by subclasses which parse those parameters. */ protected String paramsToString() { if (params == null) { return ""; } else if (algParams != null) { return algParams.toString(); } else { return ", params unparsed"; } } /** * Returns true iff the argument indicates the same algorithm * with the same parameters. */ public boolean equals(AlgorithmId other) { if (!algid.equals(other.algid)) return false; else if (params == null && other.params == null) return true; else if (params == null) return false; else return params.equals(other.params); } /** * Compares this AlgorithmID to another. If algorithm parameters are * available, they are compared. Otherwise, just the object IDs * for the algorithm are compared. * * @param other preferably an AlgorithmId, else an ObjectIdentifier */ @Override public boolean equals(Object other) { if (other instanceof AlgorithmId) return equals((AlgorithmId) other); else if (other instanceof ObjectIdentifier) return equals((ObjectIdentifier) other); else return false; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((algParams == null) ? 0 : algParams.hashCode()); result = prime * result + ((algid == null) ? 0 : algid.hashCode()); result = prime * result + ((params == null) ? 0 : params.hashCode()); result = prime * result + ((paramsString == null) ? 0 : paramsString.hashCode()); return result; } /** * Compares two algorithm IDs for equality. Returns true iff * they are the same algorithm, ignoring algorithm parameters. */ public final boolean equals(ObjectIdentifier id) { return algid.equals(id); } public static AlgorithmParameters createPSSAlgorithmParametersFromData(byte[] der) throws Exception { if (der == null) { throw new Exception("Invalid input data."); } AlgorithmParameters pssParams = null; try { pssParams = AlgorithmParameters.getInstance("RSAPSSAlgorithmParameters", "Mozilla-JSS"); } catch (NoSuchProviderException e) { throw new Exception(e); } try { pssParams.init(der); } catch (IOException e) { throw new Exception("Error intializing RSAPSS parameters: " + e); } return pssParams; } /** * Used to create the PSS algorithm params needed for RSA PSS signatures. */ public static AlgorithmParameters createPSSAlgorithmParameters(String algName) throws IllegalArgumentException, NoSuchProviderException, InvalidParameterSpecException, NoSuchAlgorithmException { if (algName == null) { throw new IllegalArgumentException("Invalid Algorithm name input."); } if (!algName.contains("PSS")) { throw new IllegalArgumentException("PSS Algorithm name not supported."); } AlgorithmParameters pssParams = null; PSSParameterSpec pssSpec = null; // Make sure we are in the RSA PSS family // Only support for now RSAPSS with SHA256 , 384, and 512 // Resulting in different PSSParameterSpec values if ("SHA256withRSA/PSS".equals(algName)) { // Support the most often used SHA-256 hash alg version . pssSpec = new PSSParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, 1); } else if ("SHA384withRSA/PSS".equals(algName)) { pssSpec = new PSSParameterSpec("SHA-384", "MGF1", MGF1ParameterSpec.SHA384, 48, 1); } else if ("SHA512withRSA/PSS".equals(algName)) { pssSpec = new PSSParameterSpec("SHA-512", "MGF1", MGF1ParameterSpec.SHA512, 64, 1); } else { throw new IllegalArgumentException("Unsupported algorithm: " + algName); } pssParams = AlgorithmParameters.getInstance("RSAPSSAlgorithmParameters", "Mozilla-JSS"); pssParams.init(pssSpec); return pssParams; } /*****************************************************************/ /* * HASHING ALGORITHMS */ private static final int MD2_data[] = { 1, 2, 840, 113549, 2, 2 }; private static final int MD5_data[] = { 1, 2, 840, 113549, 2, 5 }; // sha = { 1, 3, 14, 3, 2, 18 }; private static final int SHA1_OIW_data[] = { 1, 3, 14, 3, 2, 26 }; private static final int SHA256_data[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 }; private static final int SHA384_data[] = { 2, 16, 840, 1, 101, 3, 4, 2, 2 }; private static final int SHA512_data[] = { 2, 16, 840, 1, 101, 3, 4, 2, 3 }; private static final int MGF1_data[] = { 1,2,840,113549,1,1,8 }; /** * Algorithm ID for the MD2 Message Digest Algorthm, from RFC 1319. * OID = 1.2.840.113549.2.2 */ public static final ObjectIdentifier MD2_oid = new ObjectIdentifier(MD2_data); /** * Algorithm ID for the MD5 Message Digest Algorthm, from RFC 1321. * OID = 1.2.840.113549.2.5 */ public static final ObjectIdentifier MD5_oid = new ObjectIdentifier(MD5_data); /** * Algorithm ID for the SHA1 Message Digest Algorithm, from FIPS 180-1. * This is sometimes called "SHA", though that is often confusing since * many people refer to FIPS 180 (which has an error) as defining SHA. * OID = 1.3.14.3.2.26 */ public static final ObjectIdentifier SHA_oid = new ObjectIdentifier(SHA1_OIW_data); public static final ObjectIdentifier SHA256_oid = new ObjectIdentifier(SHA256_data); public static final ObjectIdentifier SHA384_oid = new ObjectIdentifier(SHA384_data); public static final ObjectIdentifier SHA512_oid = new ObjectIdentifier(SHA512_data); public static final ObjectIdentifier MGF1_oid = new ObjectIdentifier(MGF1_data); /* * COMMON PUBLIC KEY TYPES */ private static final int DH_data[] = { 1, 2, 840, 113549, 1, 3, 1 }; private static final int DH_PKIX_data[] = { 1, 2, 840, 10046, 2, 1 }; private static final int DSA_OIW_data[] = { 1, 3, 14, 3, 2, 12 }; private static final int DSA_PKIX_data[] = { 1, 2, 840, 10040, 4, 1 }; private static final int RSA_data[] = { 1, 2, 5, 8, 1, 1 }; private static final int RSAEncryption_data[] = { 1, 2, 840, 113549, 1, 1, 1 }; private static final int ANSI_X962_public_key_data[] = { 1, 2, 840, 10045, 2, 1 }; private static final int ANSI_X962_sha1_with_ec_data[] = { 1, 2, 840, 10045, 4, 1 }; public static final ObjectIdentifier ANSIX962_EC_Public_Key_oid = new ObjectIdentifier(ANSI_X962_public_key_data); public static final ObjectIdentifier ANSIX962_SHA1_With_EC_oid = new ObjectIdentifier(ANSI_X962_sha1_with_ec_data); /* * Note the preferred OIDs are named simply with no "OIW" or * "PKIX" in them, even though they may point to data from these * specs; e.g. SHA_oid, DH_oid, DSA_oid, SHA1WithDSA_oid... */ /** * Algorithm ID for Diffie Hellman Key agreement, from PKCS #3. * Parameters include public values P and G, and may optionally specify * the length of the private key X. Alternatively, algorithm parameters * may be derived from another source such as a Certificate Authority's * certificate. * OID = 1.2.840.113549.1.3.1 */ public static final ObjectIdentifier DH_oid = new ObjectIdentifier(DH_data); /** * Algorithm ID for the Diffie Hellman Key Agreement (DH), from the * IETF PKIX IPKI Part I. * Parameters may include public values P and G. * OID = 1.2.840.10046.2.1 */ public static final ObjectIdentifier DH_PKIX_oid = new ObjectIdentifier(DH_PKIX_data); /** * Algorithm ID for the Digital Signing Algorithm (DSA), from the * NIST OIW Stable Agreements part 12. * Parameters may include public values P, Q, and G; or these may be * derived from * another source such as a Certificate Authority's certificate. * OID = 1.3.14.3.2.12 */ public static final ObjectIdentifier DSA_OIW_oid = new ObjectIdentifier(DSA_OIW_data); /** * Algorithm ID for the Digital Signing Algorithm (DSA), from the * IETF PKIX IPKI Part I. * Parameters may include public values P, Q, and G; or these may be * derived from * another source such as a Certificate Authority's certificate. * OID = 1.2.840.10040.4.1 */ public static final ObjectIdentifier DSA_oid = new ObjectIdentifier(DSA_PKIX_data); /** * Algorithm ID for RSA keys used for any purpose, as defined in X.509. * The algorithm parameter is a single value, the number of bits in the * public modulus. * OID = 1.2.5.8.1.1 */ public static final ObjectIdentifier RSA_oid = new ObjectIdentifier(RSA_data); /** * Algorithm ID for RSA keys used with RSA encryption, as defined * in PKCS #1. There are no parameters associated with this algorithm. * OID = 1.2.840.113549.1.1.1 */ public static final ObjectIdentifier RSAEncryption_oid = new ObjectIdentifier(RSAEncryption_data); /* * COMMON SIGNATURE ALGORITHMS */ private static final int sha1WithEC_data[] = { 1, 2, 840, 10045, 4, 1 }; private static final int sha224WithEC_data[] = { 1, 2, 840, 10045, 4, 3, 1 }; private static final int sha256WithEC_data[] = { 1, 2, 840, 10045, 4, 3, 2 }; private static final int sha384WithEC_data[] = { 1, 2, 840, 10045, 4, 3, 3 }; private static final int sha512WithEC_data[] = { 1, 2, 840, 10045, 4, 3, 4 }; private static final int md2WithRSAEncryption_data[] = { 1, 2, 840, 113549, 1, 1, 2 }; private static final int md5WithRSAEncryption_data[] = { 1, 2, 840, 113549, 1, 1, 4 }; private static final int sha1WithRSAEncryption_data[] = { 1, 2, 840, 113549, 1, 1, 5 }; private static final int sha256WithRSAEncryption_data[] = { 1, 2, 840, 113549, 1, 1, 11 }; private static final int sha384WithRSAEncryption_data[] = { 1, 2, 840, 113549, 1, 1, 12 }; private static final int sha512WithRSAEncryption_data[] = { 1, 2, 840, 113549, 1, 1, 13 }; private static final int sha1WithRSAEncryption_OIW_data[] = { 1, 3, 14, 3, 2, 29 }; private static final int shaWithDSA_OIW_data[] = { 1, 3, 14, 3, 2, 13 }; private static final int sha1WithDSA_OIW_data[] = { 1, 3, 14, 3, 2, 27 }; private static final int dsaWithSHA1_PKIX_data[] = { 1, 2, 840, 10040, 4, 3 }; private static final int rsaPSS_data[] = { 1, 2, 840, 113549, 1, 1, 10 }; public static final ObjectIdentifier sha1WithEC_oid = new ObjectIdentifier(sha1WithEC_data); public static final ObjectIdentifier sha224WithEC_oid = new ObjectIdentifier(sha224WithEC_data); public static final ObjectIdentifier sha256WithEC_oid = new ObjectIdentifier(sha256WithEC_data); public static final ObjectIdentifier sha384WithEC_oid = new ObjectIdentifier(sha384WithEC_data); public static final ObjectIdentifier sha512WithEC_oid = new ObjectIdentifier(sha512WithEC_data); public static final ObjectIdentifier rsaPSS_oid = new ObjectIdentifier(rsaPSS_data); /** * Identifies a signing algorithm where an MD2 digest is encrypted * using an RSA private key; defined in PKCS #1. Use of this * signing algorithm is discouraged due to MD2 vulnerabilities. * OID = 1.2.840.113549.1.1.2 */ public static final ObjectIdentifier md2WithRSAEncryption_oid = new ObjectIdentifier(md2WithRSAEncryption_data); /** * Identifies a signing algorithm where an MD5 digest is * encrypted using an RSA private key; defined in PKCS #1. * OID = 1.2.840.113549.1.1.4 */ public static final ObjectIdentifier md5WithRSAEncryption_oid = new ObjectIdentifier(md5WithRSAEncryption_data); /** * The proper one for sha1/rsa */ public static final ObjectIdentifier sha1WithRSAEncryption_oid = new ObjectIdentifier(sha1WithRSAEncryption_data); /** * The proper one for sha256/rsa */ public static final ObjectIdentifier sha256WithRSAEncryption_oid = new ObjectIdentifier(sha256WithRSAEncryption_data); /** * The proper one for sha384/rsa */ public static final ObjectIdentifier sha384WithRSAEncryption_oid = new ObjectIdentifier(sha384WithRSAEncryption_data); /** * The proper one for sha512/rsa */ public static final ObjectIdentifier sha512WithRSAEncryption_oid = new ObjectIdentifier(sha512WithRSAEncryption_data); /** * Identifies a signing algorithm where an SHA1 digest is * encrypted using an RSA private key; defined in NIST OIW. * OID = 1.3.14.3.2.29 */ public static final ObjectIdentifier sha1WithRSAEncryption_OIW_oid = new ObjectIdentifier(sha1WithRSAEncryption_OIW_data); /** * Identifies the FIPS 186 "Digital Signature Standard" (DSS), where a * SHA digest is signed using the Digital Signing Algorithm (DSA). * This should not be used. * OID = 1.3.14.3.2.13 */ public static final ObjectIdentifier shaWithDSA_OIW_oid = new ObjectIdentifier(shaWithDSA_OIW_data); /** * Identifies the FIPS 186 "Digital Signature Standard" (DSS), where a * SHA1 digest is signed using the Digital Signing Algorithm (DSA). * OID = 1.3.14.3.2.27 */ public static final ObjectIdentifier sha1WithDSA_OIW_oid = new ObjectIdentifier(sha1WithDSA_OIW_data); /** * Identifies the FIPS 186 "Digital Signature Standard" (DSS), where a * SHA1 digest is signed using the Digital Signing Algorithm (DSA). * OID = 1.2.840.10040.4.3 */ public static final ObjectIdentifier sha1WithDSA_oid = new ObjectIdentifier(dsaWithSHA1_PKIX_data); /** * Supported signing algorithms for a DSA key. */ public static final String[] DSA_SIGNING_ALGORITHMS = new String[] { "SHA1withDSA" }; /** * Supported signing algorithms for a RSA key. */ public static final String[] RSA_SIGNING_ALGORITHMS = new String[] { "SHA256withRSA", "SHA384withRSA", "SHA512withRSA", "SHA1withRSA", "SHA256withRSA/PSS", "SHA384withRSA/PSS", "SHA512withRSA/PSS" }; public static final String[] EC_SIGNING_ALGORITHMS = new String[] { "SHA256withEC", "SHA384withEC", "SHA512withEC", "SHA1withEC" }; /** * All supported signing algorithms. */ public static final String[] ALL_SIGNING_ALGORITHMS = new String[] { "SHA256withRSA", "SHA384withRSA", "SHA512withRSA", "SHA1withRSA", "SHA256withRSA/PSS", "SHA384withRSA/PSS", "SHA512withRSA/PSS", "SHA256withEC", "SHA384withEC", "SHA512withEC", "SHA1withEC" }; } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/Attribute.java000066400000000000000000000246061412550063600270020ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.OutputStream; import java.io.Serializable; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerEncoder; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** * An attribute, as identified by some attribute ID, has some particular values. * Values are as a rule ASN.1 printable strings. A conventional set of type IDs * is recognized when parsing. The following shows the syntax: * *

 *
 *    Attribute	::= SEQUENCE {
 * type		AttributeType,
 * 	value		SET OF AttributeValue
 *              	-- at least one value is required --}
 *
 *    AttributeType	::= OBJECT IDENTIFIER
 *
 *    AttributeValue	::= ANY
 *
 * 
* * Refer to draft-ietf-pkix-ipki-part1-11 for the support attributes listed on * page 96 of the internet draft. The are listed here for easy reference: name, * common name, surname, given name, initials, generation qualifier, dn qualifier, * country name, locality name, state or province name, organization name, organization * unit name, title, pkcs9 email. Not all the attributes are supported. Please check * the X500NameAttrMap for defined attributes. * * @author Christine Ho */ public final class Attribute implements Serializable, DerEncoder { /** * */ private static final long serialVersionUID = -931486084625476764L; //private variables ObjectIdentifier oid; Vector valueSet = new Vector(); transient protected X500NameAttrMap attrMap; //========== CONSTRUCTOR ================================== /** * Construct an attribute from attribute type and attribute value * * @param oid the object identifier of the attribute type * @param value the value string */ public Attribute(ObjectIdentifier oid, String value) throws IOException { //pre-condition verification if ((oid == null) || (value == null)) throw new IOException("Invalid Input - null passed"); attrMap = X500NameAttrMap.getDefault(); this.oid = oid; valueSet.addElement(value); } /** * Construct an attribute from attribute type and attribute values * * @param oid the object identifier of the attribute type * @param values String value vector */ public Attribute(ObjectIdentifier oid, Vector values) throws IOException { //pre-condition verification if ((oid == null) || (values == null)) throw new IOException("Invalid Input - null passed"); attrMap = X500NameAttrMap.getDefault(); this.oid = oid; //copy the value into the valueSet list Enumeration vals = values.elements(); while (vals.hasMoreElements()) { valueSet.addElement(vals.nextElement()); } } /** * Construct an attribute from attribute type and attribute values * * @param attr oid attribute type string CN,OU,O,C,L,TITLE,ST,STREET,UID,MAIL,E,DC * @param values String value vector */ public Attribute(String attr, Vector values) throws IOException { //pre-condition verification if ((attr == null) || (values == null)) throw new IOException("Invalid Input - null passed"); ObjectIdentifier identifier = null; try { identifier = new ObjectIdentifier(attr); } catch (Exception e) { } ObjectIdentifier id = identifier; if (identifier == null) { attrMap = X500NameAttrMap.getDefault(); id = attrMap.getOid(attr); if (id == null) throw new IOException("Attr is not supported - does not contain in attr map"); } this.oid = id; //copy the value into the valueSet list Enumeration vals = values.elements(); while (vals.hasMoreElements()) { valueSet.addElement(vals.nextElement()); } } /** * Construct an attribute from a der encoded object. This der * der encoded value should represent the attribute object. * * @param val the attribute object in der encode form. */ public Attribute(DerValue val) throws IOException { //pre-condition verification if (val == null) throw new IOException("Invalid Input - null passed"); attrMap = X500NameAttrMap.getDefault(); decodeThis(val); } //========== PUBLIC METHODS ================================== /** * Returns the OID in the Attribute. * * @return the ObjectIdentifier in this Attribute. */ public ObjectIdentifier getOid() { return oid; } /** * Returns enumeration of values in this attribute. * * @return Enumeration of values of this Attribute. */ public Enumeration getValues() { if (valueSet == null) return null; return valueSet.elements(); } /** * Encodes the Attribute to a Der output stream. * Attribute are encoded as a SEQUENCE of two elements. * * @param out The Der output stream. */ public void encode(DerOutputStream out) throws IOException { encodeThis(out); } /** * DER encode this object onto an output stream. * Implements the DerEncoder interface. * * @param out * the output stream on which to write the DER encoding. * * @exception IOException on encoding error. */ @Override public void derEncode(OutputStream out) throws IOException { encodeThis(out); } /** * Prints a string version of this extension. */ @Override public String toString() { String theoid = "Attribute: " + oid + "\n"; StringBuffer values = new StringBuffer("Values: "); Enumeration n = valueSet.elements(); if (n.hasMoreElements()) { values.append(n.nextElement()); while (n.hasMoreElements()) values.append("," + n.nextElement()); } return theoid + values.toString() + "\n"; } //========== PRIVATE METHODS ================================== //encode the attribute object private void encodeThis(OutputStream out) throws IOException { try (DerOutputStream tmp2 = new DerOutputStream()) { DerOutputStream tmp = new DerOutputStream(); tmp.putOID(oid); encodeValueSet(tmp); tmp2.write(DerValue.tag_Sequence, tmp); out.write(tmp2.toByteArray()); } } //encode the attribute object private void encodeValueSet(OutputStream out) throws IOException { try (DerOutputStream tmp2 = new DerOutputStream()) { DerOutputStream tmp = new DerOutputStream(); //get the attribute converter AVAValueConverter converter = attrMap.getValueConverter(oid); if (converter == null) { converter = new GenericValueConverter(); //throw new IOException("Converter not found: unsupported attribute type"); } //loop through all the values and encode Enumeration vals = valueSet.elements(); while (vals.hasMoreElements()) { String val = vals.nextElement(); DerValue derobj = converter.getValue(val); derobj.encode(tmp); } tmp2.write(DerValue.tag_SetOf, tmp); out.write(tmp2.toByteArray()); } } //decode the attribute object private void decodeThis(DerValue val) throws IOException { //pre-condition verification if (val == null) { throw new IOException("Invalid Input - null passed."); } if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for Attribute."); } if (val.data.available() == 0) { throw new IOException("No data available in " + "passed DER encoded value."); } this.oid = val.data.getDerValue().getOID(); if (val.data.available() == 0) { throw new IOException("Invalid encoding for Attribute - value missing"); } decodeValueSet(val.data.getDerValue()); if (this.oid == null) throw new IOException("Invalid encoding for Attribute - OID missing"); } //decode the attribute value set private void decodeValueSet(DerValue val) throws IOException { //pre-condition verification if (val == null) { throw new IOException("Invalid Input - null passed."); } AVAValueConverter converter = attrMap.getValueConverter(this.oid); if (converter == null) { converter = new GenericValueConverter(); //throw new IOException("Attribute is not supported - not in attr map"); } if (val.tag != DerValue.tag_SetOf) { throw new IOException("Invalid encoding for Attribute Value Set."); } if (val.data.available() == 0) { throw new IOException("No data available in " + "passed DER encoded attribute value set."); } //get the value set while (val.data.available() != 0) { DerValue value = val.data.getDerValue(); valueSet.addElement(converter.getAsString(value)); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/AuthorityKeyIdentifierExtension.java000066400000000000000000000300351412550063600333710ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class represents the Authority Key Identifier Extension. * *

* The authority key identifier extension provides a means of identifying the particular public key used to sign a * certificate. This extension would be used where an issuer has multiple signing keys (either due to multiple * concurrent key pairs or due to changeover). *

* The ASN.1 syntax for this is: * *

 * AuthorityKeyIdentifier ::= SEQUENCE {
 *    keyIdentifier             [0] KeyIdentifier           OPTIONAL,
 *    authorityCertIssuer       [1] GeneralNames            OPTIONAL,
 *    authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL
 * }
 * KeyIdentifier ::= OCTET STRING
 * 
* * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.9 * @see Extension * @see CertAttrSet */ public class AuthorityKeyIdentifierExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -157913621972354170L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.AuthorityKeyIdentifier"; /** * Attribute names. */ public static final String NAME = "AuthorityKeyIdentifier"; public static final String KEY_ID = "key_id"; public static final String AUTH_NAME = "auth_name"; public static final String SERIAL_NUMBER = "serial_number"; // Private data members private static final byte TAG_ID = 0; private static final byte TAG_NAMES = 1; private static final byte TAG_SERIAL_NUM = 2; private KeyIdentifier id = null; private GeneralNames names = null; private SerialNumber serialNum = null; // Encode only the extension value private void encodeThis() throws IOException { try (DerOutputStream tmp = new DerOutputStream(); DerOutputStream seq = new DerOutputStream()) { if (id != null) { DerOutputStream tmp1 = new DerOutputStream(); id.encode(tmp1); tmp.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, false, TAG_ID), tmp1); } try { if (names != null) { DerOutputStream tmp1 = new DerOutputStream(); names.encode(tmp1); tmp.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, true, TAG_NAMES), tmp1); } } catch (Exception e) { throw new IOException(e); } if (serialNum != null) { DerOutputStream tmp1 = new DerOutputStream(); serialNum.encode(tmp1); tmp.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, false, TAG_SERIAL_NUM), tmp1); } seq.write(DerValue.tag_Sequence, tmp); this.extensionValue = seq.toByteArray(); } } /** * Exposed critical parameter. 99/11/03 */ public AuthorityKeyIdentifierExtension(boolean critical, KeyIdentifier kid, GeneralNames name, SerialNumber sn) throws IOException { this.id = kid; this.names = name; this.serialNum = sn; this.extensionId = PKIXExtensions.AuthorityKey_Id; this.critical = critical; encodeThis(); } /** * The default constructor for this extension. Null parameters make * the element optional (not present). * * @param kid the KeyIdentifier associated with this extension. * @param name the GeneralNames associated with this extension * @param sn the CertificateSerialNumber associated with * this extension. * @exception IOException on error. */ public AuthorityKeyIdentifierExtension(KeyIdentifier kid, GeneralNames name, SerialNumber sn) throws IOException { this.id = kid; this.names = name; this.serialNum = sn; this.extensionId = PKIXExtensions.AuthorityKey_Id; this.critical = false; encodeThis(); } /** * Create the extension from the passed DER encoded value of the same. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public AuthorityKeyIdentifierExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.AuthorityKey_Id; this.critical = critical.booleanValue(); if (!(value instanceof byte[])) throw new IOException("Illegal argument type"); int len = Array.getLength(value); byte[] extValue = new byte[len]; System.arraycopy(value, 0, extValue, 0, len); this.extensionValue = extValue; DerValue val = new DerValue(extValue); if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for " + "AuthorityKeyIdentifierExtension."); } // NB. this is always encoded with the IMPLICIT tag // The checks only make sense if we assume implicit tagging, // with explicit tagging the form is always constructed. while (val.data.available() != 0) { DerValue opt = val.data.getDerValue(); if (opt.isContextSpecific(TAG_ID) && !opt.isConstructed()) { if (id != null) throw new IOException("Duplicate KeyIdentifier in " + "AuthorityKeyIdentifier."); opt.resetTag(DerValue.tag_OctetString); id = new KeyIdentifier(opt); } else if (opt.isContextSpecific(TAG_NAMES) && opt.isConstructed()) { if (names != null) throw new IOException("Duplicate GeneralNames in " + "AuthorityKeyIdentifier."); try { opt.resetTag(DerValue.tag_Sequence); names = new GeneralNames(opt); } catch (GeneralNamesException e) { throw new IOException(e); } } else if (opt.isContextSpecific(TAG_SERIAL_NUM) && !opt.isConstructed()) { if (serialNum != null) throw new IOException("Duplicate SerialNumber in " + "AuthorityKeyIdentifier."); opt.resetTag(DerValue.tag_Integer); serialNum = new SerialNumber(opt); } else throw new IOException("Invalid encoding of " + "AuthorityKeyIdentifierExtension."); } } /** * Return the object as a string. */ @Override public String toString() { String s = super.toString() + "AuthorityKeyIdentifier [\n"; if (id != null) { s += id.toString(); } if (names != null) { s += names.toString() + "\n"; } if (serialNum != null) { s += serialNum.toString() + "\n"; } return (s + "]\n"); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the OutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on error. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { extensionId = PKIXExtensions.AuthorityKey_Id; critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { clearValue(); if (name.equalsIgnoreCase(KEY_ID)) { if (!(obj instanceof KeyIdentifier)) { throw new IOException("Attribute value should be of " + "type KeyIdentifier."); } id = (KeyIdentifier) obj; } else if (name.equalsIgnoreCase(AUTH_NAME)) { if (!(obj instanceof GeneralNames)) { throw new IOException("Attribute value should be of " + "type GeneralNames."); } names = (GeneralNames) obj; } else if (name.equalsIgnoreCase(SERIAL_NUMBER)) { if (!(obj instanceof SerialNumber)) { throw new IOException("Attribute value should be of " + "type SerialNumber."); } serialNum = (SerialNumber) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:AuthorityKeyIdentifier."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(KEY_ID)) { return (id); } else if (name.equalsIgnoreCase(AUTH_NAME)) { return (names); } else if (name.equalsIgnoreCase(SERIAL_NUMBER)) { return (serialNum); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:AuthorityKeyIdentifier."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(KEY_ID)) { id = null; } else if (name.equalsIgnoreCase(AUTH_NAME)) { names = null; } else if (name.equalsIgnoreCase(SERIAL_NUMBER)) { serialNum = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:AuthorityKeyIdentifier."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(KEY_ID); elements.addElement(AUTH_NAME); elements.addElement(SERIAL_NUMBER); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/BasicConstraintsExtension.java000066400000000000000000000230271412550063600322010ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class represents the Basic Constraints Extension. * *

* The basic constraints extension identifies whether the subject of the certificate is a CA and how deep a * certification path may exist through that CA. * *

 * The ASN.1 syntax for this extension is:
 * BasicConstraints ::= SEQUENCE {
 *     cA                BOOLEAN DEFAULT FALSE,
 *     pathLenConstraint INTEGER (0..MAX) OPTIONAL
 * }
 * 
* * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.7 * @see CertAttrSet * @see Extension */ public class BasicConstraintsExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 6213957094939885889L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.BasicConstraints"; /** * Attribute names. */ public static final String NAME = "BasicConstraints"; public static final String IS_CA = "is_ca"; public static final String PATH_LEN = "path_len"; // Private data members private boolean ca = false; private int pathLen = -1; // Encode this extension value private void encodeThis() throws IOException { try (DerOutputStream out = new DerOutputStream()) { DerOutputStream tmp = new DerOutputStream(); if (ca) { tmp.putBoolean(ca); } if (pathLen >= 0) { tmp.putInteger(new BigInt(pathLen)); } out.write(DerValue.tag_Sequence, tmp); this.extensionValue = out.toByteArray(); } } /** * Default constructor for this object. * * @param ca true, if the subject of the Certificate is a CA. * @param len specifies the depth of the certification path. */ public BasicConstraintsExtension(boolean ca, int len) throws IOException { this.ca = ca; this.pathLen = len; this.extensionId = PKIXExtensions.BasicConstraints_Id; if (ca) { critical = true; } else { critical = false; } encodeThis(); } /** * Default constructor for this object. * * @param ca true, if the subject of the Certificate is a CA. * @param len specifies the depth of the certification path. */ public BasicConstraintsExtension(boolean ca, boolean critical, int len) throws IOException { this.ca = ca; this.pathLen = len; this.extensionId = PKIXExtensions.BasicConstraints_Id; this.critical = critical; encodeThis(); } /** * Create the extension from the passed DER encoded value of the same. * * @param value the DER encoded value of the extension. * @exception IOException on error. */ public BasicConstraintsExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.BasicConstraints_Id; this.critical = critical.booleanValue(); if (value instanceof byte[]) { int len = Array.getLength(value); byte[] extValue = new byte[len]; System.arraycopy(value, 0, extValue, 0, len); this.extensionValue = extValue; DerValue val = new DerValue(extValue); if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding of BasicConstraints"); } // non-CA cert with no limit to certification path length if (val.data == null || val.data.available() < 1) { this.ca = false; this.pathLen = -1; return; } DerValue opt = val.data.getDerValue(); if (opt.tag != DerValue.tag_Boolean) { this.ca = false; } else { this.ca = true; if (val.data.available() != 0) { opt = val.data.getDerValue(); } else { this.pathLen = -1; return; } } if (opt.tag != DerValue.tag_Integer) { throw new IOException("Invalid encoding of BasicConstraints"); } this.pathLen = (opt.getInteger()).toInt(); /* * Activate this check once again after PKIX profiling * is a standard and this check no longer imposes an * interoperability barrier. * if (ca) { * if (!this.critical) { * throw new IOException("Criticality cannot be false for CA."); * } * } */ } else throw new IOException("Invalid argument type"); } /** * Return user readable form of extension. */ @Override public String toString() { String s = super.toString() + "BasicConstraints:[\n"; s += ((ca) ? ("CA:true") : ("CA:false")) + "\n"; if (pathLen >= 0) { s += "PathLen:" + pathLen + "\n"; } else { s += "PathLen: undefined\n"; } return (s + "]\n"); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Encode this extension value to the output stream. * * @param out the DerOutputStream to encode the extension to. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { this.extensionId = PKIXExtensions.BasicConstraints_Id; /* #57286 - so that profile can set critiality */ /* if (ca) { critical = true; } else { critical = false; } */ encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { clearValue(); if (name.equalsIgnoreCase(IS_CA)) { if (!(obj instanceof Boolean)) { throw new IOException("Attribute value should be of type Boolean."); } ca = ((Boolean) obj).booleanValue(); } else if (name.equalsIgnoreCase(PATH_LEN)) { if (!(obj instanceof Integer)) { throw new IOException("Attribute value should be of type Integer."); } pathLen = ((Integer) obj).intValue(); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:BasicConstraints."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(IS_CA)) { return (Boolean.valueOf(ca)); } else if (name.equalsIgnoreCase(PATH_LEN)) { return (Integer.valueOf(pathLen)); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:BasicConstraints."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(IS_CA)) { ca = false; } else if (name.equalsIgnoreCase(PATH_LEN)) { pathLen = -1; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:BasicConstraints."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(IS_CA); elements.addElement(PATH_LEN); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CIDRNetmask.java000066400000000000000000000045631412550063600271030ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2018 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.nio.ByteBuffer; /** * Netmask that is the number of significant bits. */ public class CIDRNetmask { private int n; public CIDRNetmask(String s) { this(Integer.parseInt(s)); } public CIDRNetmask(int n) { if (n < 0) throw new InvalidNetmaskException("cannot be negative"); this.n = n; } /** * Write the netmask into a byte buffer. * * Throw InvalidNetmaskException if negative or if the * size exceeds the size of the address type inferred * from the remaining buffer space (which must be 4 * bytes for IPv4 and 16 bytes for IPv6). * * exceeds the size of the buffer */ protected void write(ByteBuffer buf) { // determine type of addr based on bytes left in buffer int remaining = buf.remaining(); int bits = 0; if (remaining == 4) bits = 32; else if (remaining == 16) bits = 128; else throw new InvalidNetmaskException( "cannot determine type of address for netmask"); if (n > bits) throw new InvalidNetmaskException("netmask exceed address size"); int maskSigBits = n; for (; remaining > 0; remaining--) { int maskByteSigBits = Math.min(8, maskSigBits); byte maskByte = (byte) (0xff - (0xff >> maskByteSigBits)); buf.put(maskByte); maskSigBits = Math.max(maskSigBits - 8, 0); } } @Override public String toString() { return "/" + n; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CPSuri.java000066400000000000000000000033421412550063600261760ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * Represent the CPSuri Qualifier. * * CPSuri ::= IA5String; * * @author Thomas Kwan */ public class CPSuri extends Qualifier { /** * */ private static final long serialVersionUID = -2814961293159006960L; private String mURI = null; public CPSuri(String uri) { mURI = uri; } public CPSuri(DerValue val) throws IOException { mURI = val.getIA5String(); } /** * Write the PolicyQualifier to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException on errors. */ @Override public void encode(DerOutputStream out) throws IOException { out.putIA5String(mURI); } public String getURI() { return mURI; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CRLDistributionPoint.java000066400000000000000000000425051412550063600310670ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.netscape.security.util.BitArray; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BIT_STRING; import org.mozilla.jss.asn1.EXPLICIT; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** *
 * DistributionPoint ::= SEQUENCE {
 *      distributionPoint       [0]     DistributionPointName OPTIONAL,
 *      reasons                 [1]     ReasonFlags OPTIONAL,
 *      cRLIssuer               [2]     GeneralNames OPTIONAL }
 *
 * DistributionPointName ::= CHOICE {
 *      fullName                [0]     GeneralNames,
 *      nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
 *
 * ReasonFlags ::= BIT STRING {
 *      unused                  (0),
 *      keyCompromise           (1),
 *      cACompromise            (2),
 *      affiliationChanged      (3),
 *      superseded              (4),
 *      cessationOfOperation    (5),
 *      certificateHold         (6) }
 * 
*/ public class CRLDistributionPoint implements ASN1Value { // at most one of the two following may be specified: private GeneralNames fullName; private RDN relativeName; // cache encoding of fullName private ANY fullNameEncoding; private BitArray reasons; // optional, may be null private GeneralNames CRLIssuer; // optional, may be null private ANY CRLIssuerEncoding; // default constructor does nothing. /** * Returns the fullName of the DistributionPointName, which may be null. */ public GeneralNames getFullName() { return fullName; } /** * Returns the relativeName of the DistributionPointName, which may be null. */ public RDN getRelativeName() { return relativeName; } /** * Sets the fullName of the DistributionPointName. It may be set to null. * If it is set to a non-null value, relativeName will be * set to null, because at most one of these two attributes * can be specified at a time. * * @exception GeneralNamesException If an error occurs encoding the * name. */ public void setFullName(GeneralNames fullName) throws GeneralNamesException, IOException { this.fullName = fullName; if (fullName != null) { // encode the name to catch any problems with it DerOutputStream derOut = new DerOutputStream(); fullName.encode(derOut); try { ANY raw = new ANY(derOut.toByteArray()); ByteArrayOutputStream bos = new ByteArrayOutputStream(); raw.encodeWithAlternateTag(Tag.get(0), bos); fullNameEncoding = new ANY(bos.toByteArray()); } catch (InvalidBERException e) { // assume this won't happen, since it would imply a bug // in DerOutputStream throw new GeneralNamesException(e.toString()); } this.relativeName = null; } } /** * Sets the relativeName of the DistributionPointName. It may be set to null. * If it is set to a non-null value, fullName will be * set to null, because at most one of these two attributes * can be specified at a time. */ public void setRelativeName(RDN relativeName) { this.relativeName = relativeName; if (relativeName != null) { this.fullName = null; } } /** * Returns the reason flags for this distribution point. May be null. */ public BitArray getReasons() { return reasons; } /** * Sets the reason flags for this distribution point. May be set to null. */ public void setReasons(BitArray reasons) { this.reasons = reasons; } /** * Returns the CRLIssuer for the CRL at this distribution point. * May be null. */ public GeneralNames getCRLIssuer() { return CRLIssuer; } /** * Sets the CRLIssuer for the CRL at this distribution point. * May be set to null. * * @exception GeneralNamesException If an error occurs encoding the name. */ public void setCRLIssuer(GeneralNames CRLIssuer) throws GeneralNamesException, IOException { this.CRLIssuer = CRLIssuer; if (CRLIssuer != null) { // encode the name to catch any problems with it DerOutputStream derOut = new DerOutputStream(); CRLIssuer.encode(derOut); try { ANY raw = new ANY(derOut.toByteArray()); ByteArrayOutputStream bos = new ByteArrayOutputStream(); raw.encodeWithAlternateTag(Tag.get(2), bos); CRLIssuerEncoding = new ANY(bos.toByteArray()); } catch (InvalidBERException e) { throw new GeneralNamesException(e.toString()); } } } ///////////////////////////////////////////////////////////// // DER encoding ///////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); DerOutputStream derOut; try { // Encodes the DistributionPointName. Because DistributionPointName // is a CHOICE, the [0] tag is forced to be EXPLICIT. if (fullName != null) { EXPLICIT distPoint = new EXPLICIT(Tag.get(0), fullNameEncoding); seq.addElement(distPoint); } else if (relativeName != null) { derOut = new DerOutputStream(); relativeName.encode(derOut); ANY rn = new ANY(derOut.toByteArray()); EXPLICIT raw = new EXPLICIT(Tag.get(1), rn); ByteArrayOutputStream bos = new ByteArrayOutputStream(); raw.encode(bos); ANY distPointName = new ANY(bos.toByteArray()); EXPLICIT distPoint = new EXPLICIT(Tag.get(0), distPointName); seq.addElement(distPoint); } // Encodes the ReasonFlags. if (reasons != null) { derOut = new DerOutputStream(); derOut.putUnalignedBitString(reasons); ANY raw = new ANY(derOut.toByteArray()); ByteArrayOutputStream bos = new ByteArrayOutputStream(); raw.encodeWithAlternateTag(Tag.get(1), bos); ANY reasonEncoding = new ANY(bos.toByteArray()); seq.addElement(Tag.get(1), reasonEncoding); } // Encodes the CRLIssuer if (CRLIssuer != null) { seq.addElement(Tag.get(2), CRLIssuerEncoding); } seq.encode(implicitTag, ostream); } catch (InvalidBERException e) { // this shouldn't happen unless there is a bug in one of // the Sun encoding classes throw new IOException(e.toString()); } } // Template singleton private static Template templateInstance = new Template(); /** * Returns an instance of a template for decoding a CRLDistributionPoint. */ public static Template getTemplate() { return templateInstance; } public static void main(String args[]) throws GeneralNamesException, IOException, InvalidBERException { ByteArrayOutputStream bos = null; FileOutputStream fos = null; try { if (args.length != 1) { System.out.println("Usage: CRLDistributionPoint "); System.exit(-1); } bos = new ByteArrayOutputStream(); SEQUENCE cdps = new SEQUENCE(); // URI only CRLDistributionPoint cdp = new CRLDistributionPoint(); URIName uri = new URIName("http://www.mycrl.com/go/here"); GeneralNames generalNames = new GeneralNames(); generalNames.addElement(uri); cdp.setFullName(generalNames); cdps.addElement(cdp); // DN only cdp = new CRLDistributionPoint(); X500Name dn = new X500Name("CN=Otis Smith,E=otis@fedoraproject.org" + ",OU=Certificate Server,O=Fedora,C=US"); generalNames = new GeneralNames(); generalNames.addElement(dn); cdp.setFullName(generalNames); cdps.addElement(cdp); // DN + reason BitArray ba = new BitArray(5, new byte[] { (byte) 0x28 }); cdp = new CRLDistributionPoint(); cdp.setFullName(generalNames); cdp.setReasons(ba); cdps.addElement(cdp); // relative DN + reason + crlIssuer cdp = new CRLDistributionPoint(); RDN rdn = new RDN("OU=foobar dept"); cdp.setRelativeName(rdn); cdp.setReasons(ba); cdp.setCRLIssuer(generalNames); cdps.addElement(cdp); cdps.encode(bos); byte[] encoded = bos.toByteArray(); fos = new FileOutputStream(args[0]); fos.write(encoded); SEQUENCE.OF_Template seqt = new SEQUENCE.OF_Template(getTemplate()); cdps = (SEQUENCE) ASN1Util.decode(seqt, encoded); int size = cdps.size(); System.out.println("Total number of CDPs: " + size); for (int i = 0; i < size; i++) { System.out.println("\nCDP " + i); cdp = (CRLDistributionPoint) cdps.elementAt(i); GeneralNames gn = cdp.getFullName(); if (gn == null) { System.out.println("No full name"); } else { System.out.println(gn); } rdn = cdp.getRelativeName(); if (rdn == null) { System.out.println("No relative name"); } else { System.out.println(rdn); } if (cdp.getReasons() == null) { System.out.println("No reasons"); } else { System.out.println(cdp.getReasons()); } gn = cdp.getCRLIssuer(); if (gn == null) { System.out.println("No cRLIssuer"); } else { System.out.println(gn); } } System.out.println("Done"); } finally { if (bos != null) { bos.close(); } if (fos != null) { fos.close(); } if (fos != null) { fos.close(); } } } /** * Template for decoding CRLDistributionPoint. */ public static class Template implements ASN1Template { @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { CRLDistributionPoint cdp = new CRLDistributionPoint(); // // construct the top-level sequence // SEQUENCE.Template seqt = SEQUENCE.getTemplate(); // distributionPoint seqt.addOptionalElement( new EXPLICIT.Template(Tag.get(0), ANY.getTemplate())); // reasons seqt.addOptionalElement(Tag.get(1), BIT_STRING.getTemplate()); // cRLIssuer // This will have a tag of 2, but we can't say that here // because ANYs can't have implicit tags. We don't need to say // it, because we do check the tags on the other two elements // in the sequence, so we'll know if we get this one. seqt.addOptionalElement(ANY.getTemplate()); // // decode the top-level sequence // SEQUENCE top = (SEQUENCE) seqt.decode(implicitTag, istream); // decode the distribution point name if (top.elementAt(0) != null) { EXPLICIT exp = (EXPLICIT) top.elementAt(0); ANY distPoint = (ANY) exp.getContent(); if (distPoint.getTag().equals(Tag.get(0))) { // fullName try { DerValue dv = new DerValue(distPoint.getEncoded()); //toFile("encodedFullName", distPoint.getEncoded()); dv.resetTag(DerValue.tag_Sequence); cdp.setFullName(new GeneralNames(dv)); } catch (GeneralNamesException e) { throw new InvalidBERException("fullName: " + e.toString()); } catch (IOException e) { throw new InvalidBERException("fullName: " + e.toString()); } } else if (distPoint.getTag().equals(Tag.get(1))) { // relative name try { DerValue dv = new DerValue(distPoint.getEncoded()); /* dv is as follows: 0 12: [1] { 2 10: SET { 4 8: SEQUENCE { 6 3: OBJECT IDENTIFIER commonName (2 5 4 3) 11 1: PrintableString 'x' : } : } : } */ dv = dv.data.getDerValue(); // skipping the tag /* after the skipping, we have: 0 10: SET { 2 8: SEQUENCE { 4 3: OBJECT IDENTIFIER commonName (2 5 4 3) 9 1: PrintableString 'x' : } : } */ dv.resetTag(DerValue.tag_Set); cdp.setRelativeName(new RDN(dv)); } catch (IOException e) { throw new InvalidBERException("relativeName " + e.toString()); } } else { throw new InvalidBERException( "Unknown tag " + distPoint.getTag() + " in distributionPoint"); } } // decode the reasons if (top.elementAt(1) != null) { BIT_STRING bs = (BIT_STRING) top.elementAt(1); byte[] bits = bs.getBits(); cdp.setReasons( new BitArray((bits.length * 8) - bs.getPadCount(), bits)); } // decode the cRLIssuer if (top.elementAt(2) != null) { ANY issuer = (ANY) top.elementAt(2); if (!issuer.getTag().equals(Tag.get(2))) { throw new InvalidBERException("Invalid tag " + issuer.getTag()); } try { DerValue dv = new DerValue(issuer.getEncoded()); dv.resetTag(DerValue.tag_Sequence); cdp.setCRLIssuer(new GeneralNames(dv)); } catch (GeneralNamesException e) { throw new InvalidBERException("cRLIssuer " + e.toString()); } catch (IOException e) { throw new InvalidBERException("cRLIssuer " + e.toString()); } } return cdp; } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CRLDistributionPointsExtension.java000066400000000000000000000320161412550063600331430ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.netscape.security.util.BitArray; import org.mozilla.jss.netscape.security.util.DerOutputStream; /** * An extension that tells applications where to find the CRL for * this certificate. * *
 * cRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
 *
 * DistributionPoint ::= SEQUENCE {
 *      distributionPoint       [0]     DistributionPointName OPTIONAL,
 *      reasons                 [1]     ReasonFlags OPTIONAL,
 *      cRLIssuer               [2]     GeneralNames OPTIONAL }
 *
 * DistributionPointName ::= CHOICE {
 *      fullName                [0]     GeneralNames,
 *      nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
 *
 * ReasonFlags ::= BIT STRING {
 *      unused                  (0),
 *      keyCompromise           (1),
 *      cACompromise            (2),
 *      affiliationChanged      (3),
 *      superseded              (4),
 *      cessationOfOperation    (5),
 *      certificateHold         (6) }
 * 
*/ public class CRLDistributionPointsExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 8551761833349709229L; // vector of CRLDistributionPoint private SEQUENCE distributionPoints = new SEQUENCE(); // Cached DER-encoding to improve performance. private byte[] cachedEncoding = null; /** * This constructor is called by the CertificateExtensions class to decode * an extension whose OID indicates it is a CRLDistributionsPoints * extension. */ public CRLDistributionPointsExtension(Boolean critical, Object value) //throws IOException { try { this.extensionId = PKIXExtensions.CRLDistributionPoints_Id; this.critical = critical.booleanValue(); this.extensionValue = ((byte[]) value).clone(); // decode the value try { SEQUENCE.OF_Template seqOfCRLDP = new SEQUENCE.OF_Template(CRLDistributionPoint.getTemplate()); distributionPoints = (SEQUENCE) ASN1Util.decode(seqOfCRLDP, extensionValue); } catch (InvalidBERException e) { throw new IOException("Invalid BER-encoding: " + e, e); } } catch (IOException e) { System.out.println("Big error"); System.out.println(e); e.printStackTrace(); //throw e; } } /** * The Object Identifier for this extension. */ public static final String OID = "2.5.29.31"; /** * Creates a new CRLDistributionPoints extension, with the given * distribution point as the first element. */ public CRLDistributionPointsExtension(CRLDistributionPoint dp) { this.extensionId = PKIXExtensions.CRLDistributionPoints_Id; this.critical = false; distributionPoints.addElement(dp); } /** * Adds an additional distribution point to the end of the sequence. */ public void addPoint(CRLDistributionPoint dp) { distributionPoints.addElement(dp); cachedEncoding = null; } /** * Returns the number of distribution points in the sequence. */ public int getNumPoints() { return distributionPoints.size(); } /** * Returns the DistributionPoint at the given index in the sequence. */ public CRLDistributionPoint getPointAt(int index) { return (CRLDistributionPoint) distributionPoints.elementAt(index); } /** * Sets the criticality of this extension. PKIX dictates that this * extension SHOULD NOT be critical, so applications can make it critical * if they have a very good reason. By default, the extension is not * critical. */ @Override public void setCritical(boolean critical) { this.critical = critical; } /** * Encodes this extension to the given DerOutputStream. * This method re-encodes each time it is called, so it is not very * efficient. */ @Override public void encode(DerOutputStream out) throws IOException { extensionValue = ASN1Util.encode(distributionPoints); super.encode(out); } /** * Should be called if any change is made to this data structure * so that the cached DER encoding can be discarded. */ public void flushCachedEncoding() { cachedEncoding = null; } ///////////////////////////////////////////////////////////// // CertAttrSet interface // This interface is not really appropriate for this extension // because it is so complicated. Therefore, we only provide a // minimal implementation. ///////////////////////////////////////////////////////////// public static final String NAME = "CRLDistributionPoints"; @Override public String toString() { return NAME; } /** * DER-encodes this extension to the given OutputStream. */ @Override public void encode(OutputStream ostream) throws CertificateException, IOException { if (cachedEncoding == null) { // only re-encode if necessary DerOutputStream tmp = new DerOutputStream(); encode(tmp); cachedEncoding = tmp.toByteArray(); } ostream.write(cachedEncoding); } @Override public void decode(InputStream in) throws CertificateException, IOException { throw new IOException("Not supported"); } @Override public void set(String name, Object obj) throws CertificateException, IOException { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CRLDistributionPointsExtension"); } @Override public Object get(String name) throws CertificateException, IOException { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CRLDistributionPointsExtension"); } @Override public void delete(String name) throws CertificateException, IOException { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CRLDistributionPointsExtension"); } /* * TODO use an empty collection to generate these */ @Override public Enumeration getAttributeNames() { return (new Vector()).elements(); } @Override public String getName() { return NAME; } /** * Test driver. */ public static void main(String args[]) { BufferedOutputStream bos = null; try { if (args.length != 1) { System.out.println("Usage: CRLDistributionPointsExtentions " + ""); System.exit(-1); } bos = new BufferedOutputStream( new FileOutputStream(args[0])); // URI only CRLDistributionPoint cdp = new CRLDistributionPoint(); URIName uri = new URIName("http://www.mycrl.com/go/here"); GeneralNames generalNames = new GeneralNames(); generalNames.addElement(uri); cdp.setFullName(generalNames); CRLDistributionPointsExtension crldpExt = new CRLDistributionPointsExtension(cdp); // DN only cdp = new CRLDistributionPoint(); X500Name dn = new X500Name("CN=Otis Smith,E=otis@fedoraproject.org" + ",OU=Certificate Server,O=Fedora,C=US"); generalNames = new GeneralNames(); generalNames.addElement(dn); cdp.setFullName(generalNames); crldpExt.addPoint(cdp); // DN + reason BitArray ba = new BitArray(5, new byte[] { (byte) 0x28 }); cdp = new CRLDistributionPoint(); cdp.setFullName(generalNames); cdp.setReasons(ba); crldpExt.addPoint(cdp); // relative DN + reason + crlIssuer cdp = new CRLDistributionPoint(); RDN rdn = new RDN("OU=foobar dept"); cdp.setRelativeName(rdn); cdp.setReasons(ba); cdp.setCRLIssuer(generalNames); crldpExt.addPoint(cdp); crldpExt.setCritical(true); crldpExt.encode(bos); } catch (Exception e) { e.printStackTrace(); } finally { if (bos != null) { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * Represents a reason that a cert may be revoked. These reasons are * expressed in a ReasonFlags bit string. */ public static class Reason { private String name; private byte bitMask; private Reason() { } private Reason(String name, byte bitMask) { this.name = name; this.bitMask = bitMask; map.put(name, this); list.addElement(this); } private static Hashtable map = new Hashtable(); private static Vector list = new Vector(); public static Reason fromString(String name) { return map.get(name); } public String getName() { return name; } public byte getBitMask() { return bitMask; } /** * Given a bit array representing reason flags, extracts the reasons * and returns them as an array. * * @param bitFlags A bit vector containing reason flags. * @return An array of reasons contained in the bit vector. * May be zero-length but will not be null. */ public static Reason[] bitArrayToReasonArray(byte bitFlags) { return bitArrayToReasonArray(new byte[] { bitFlags }); } /** * Given a bit array representing reason flags, extracts the reasons * and returns them as an array. Currently, only the first byte * of the bitflags are examined. * * @param bitFlags A bit vector containing reason flags. The format * is big-endian (MSB first). Only the first byte is examined. * @return An array of reasons contained in the bit vector. * May be zero-length but will not be null. */ public static Reason[] bitArrayToReasonArray(byte[] bitFlags) { byte first = bitFlags[0]; int size = list.size(); Vector result = new Vector(); for (int i = 0; i < size; i++) { Reason r = list.elementAt(i); byte b = r.getBitMask(); if ((first & b) != 0) { result.addElement(r); } } size = result.size(); Reason[] retval = new Reason[size]; for (int i = 0; i < size; i++) { retval[i] = result.elementAt(i); } return retval; } public static final Reason UNUSED = new Reason("unused", (byte) 0x80); public static final Reason KEY_COMPROMISE = new Reason("keyCompromise", (byte) 0x40); public static final Reason CA_COMPROMISE = new Reason("cACompromise", (byte) 0x20); public static final Reason AFFILIATION_CHANGED = new Reason("affiliationChanged", (byte) 0x10); public static final Reason SUPERSEDED = new Reason("superseded", (byte) 0x08); public static final Reason CESSATION_OF_OPERATION = new Reason("cessationOfOperation", (byte) 0x04); public static final Reason CERTIFICATE_HOLD = new Reason("certificateHold", (byte) 0x02); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CRLExtensions.java000066400000000000000000000213751412550063600275370ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.security.cert.CRLException; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class defines the CRL Extensions. * * @author Hemma Prafullchandra * @version 1.4 */ public class CRLExtensions extends Vector { /** * */ private static final long serialVersionUID = 365767738692986418L; private Hashtable map; // Parse the encoded extension private void parseExtension(Extension ext) throws X509ExtensionException { try { Class extClass = OIDMap.getClass(ext.getExtensionId()); if (extClass == null) { // Unsupported extension if (ext.isCritical()) { throw new IOException("Unsupported CRITICAL extension: " + ext.getExtensionId()); } else { map.put(ext.getExtensionId().toString(), ext); addElement(ext); return; } } Class[] params = { Boolean.class, Object.class }; Constructor cons = extClass.getConstructor(params); byte[] extData = ext.getExtensionValue(); int extLen = extData.length; Object value = Array.newInstance(byte.class, extLen); for (int i = 0; i < extLen; i++) { Array.setByte(value, i, extData[i]); } Object[] passed = new Object[] { Boolean.valueOf(ext.isCritical()), value }; CertAttrSet crlExt = (CertAttrSet) cons.newInstance(passed); map.put(crlExt.getName(), (Extension) crlExt); addElement((Extension) crlExt); } catch (InvocationTargetException invk) { throw new X509ExtensionException( invk.getTargetException().getMessage()); } catch (Exception e) { throw new X509ExtensionException(e.toString()); } } /** * Default constructor. */ public CRLExtensions() { map = new Hashtable(); } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the Extension from. * @exception CRLException on decoding errors. * @exception X509ExtensionException on extension handling errors. */ public CRLExtensions(DerInputStream in) throws CRLException, X509ExtensionException { map = new Hashtable(); try { DerValue[] exts = in.getSequence(5); for (int i = 0; i < exts.length; i++) { Extension ext = new Extension(exts[i]); parseExtension(ext); } } catch (IOException e) { throw new CRLException("Parsing error: " + e.toString()); } } /** * Decode the extensions from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception CRLException on decoding or validity errors. * @exception X509ExtensionException on extension handling errors. */ public void decode(InputStream in) throws CRLException, X509ExtensionException { try { DerValue val = new DerValue(in); DerInputStream str = val.toDerInputStream(); map = new Hashtable(); DerValue[] exts = str.getSequence(5); for (int i = 0; i < exts.length; i++) { Extension ext = new Extension(exts[i]); parseExtension(ext); } } catch (IOException e) { throw new CRLException("Parsing error: " + e.toString()); } } /** * Encode the extensions in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @param isExplicit the tag indicating whether this is an entry * extension or a CRL extension. * @exception CRLException on encoding errors. */ public void encode(OutputStream out, boolean isExplicit) throws CRLException { try (DerOutputStream tmp = new DerOutputStream()) { // #381559 if (size() == 0) return; DerOutputStream extOut = new DerOutputStream(); for (int i = 0; i < size(); i++) { Object thisOne = elementAt(i); if (thisOne instanceof CertAttrSet) ((CertAttrSet) thisOne).encode(extOut); else if (thisOne instanceof Extension) ((Extension) thisOne).encode(extOut); else throw new CRLException("Illegal extension object"); } DerOutputStream seq = new DerOutputStream(); seq.write(DerValue.tag_Sequence, extOut); if (isExplicit) { tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0), seq); out.write(tmp.toByteArray()); } else { out.write(seq.toByteArray()); } } catch (IOException e) { throw new CRLException("Encoding error: " + e.toString()); } catch (CertificateException e) { throw new CRLException("Encoding error: " + e.toString()); } } /** * Get the extension with this alias. * * @param alias the identifier string for the extension to retrieve. * @exception X509ExtensionException on extension handling errors. */ public Extension get(String alias) throws X509ExtensionException { X509AttributeName attr = new X509AttributeName(alias); String name; String id = attr.getPrefix(); if (id.equalsIgnoreCase(X509CertImpl.NAME)) { // fully qualified int index = alias.lastIndexOf("."); name = alias.substring(index + 1); } else name = alias; Extension ext = map.get(name); if (ext == null) throw new X509ExtensionException("No extension found with name: " + alias); return ext; } /** * Set the extension value with this alias. * * @param alias the identifier string for the extension to set. * @param obj the Object to set the extension identified by the * alias. * @exception IOException on errors. */ public void set(String alias, Extension obj) throws IOException { map.put(alias, obj); addElement(obj); } /** * Return an enumeration of names of the extensions. * * @return an enumeration of the names of the extensions in this CRL. */ public Enumeration getElements() { return (map.elements()); } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((map == null) ? 0 : map.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; CRLExtensions other = (CRLExtensions) obj; if (map == null) { if (other.map != null) return false; } else if (!map.equals(other.map)) return false; return true; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CRLNumberExtension.java000066400000000000000000000165071412550063600305260ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.math.BigInteger; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * Represent the CRL Number Extension. * *

* This extension, if present, conveys a monotonically increasing sequence number for each CRL issued by a given CA * through a specific CA X.500 Directory entry or CRL distribution point. This extension allows users to easily * determine when a particular CRL supersedes another CRL. * * @author Hemma Prafullchandra * @version 1.2 * @see Extension * @see CertAttrSet */ public class CRLNumberExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 2992307666566322402L; /** * Attribute name. */ public static final String NAME = "CRLNumber"; public static final String NUMBER = "value"; private BigInt crlNumber = null; // Encode this extension value private void encodeThis() throws IOException { if (crlNumber == null) throw new IOException("Unintialized CRL number extension"); try (DerOutputStream os = new DerOutputStream()) { os.putInteger(this.crlNumber); this.extensionValue = os.toByteArray(); } } /** * Create a CRLNumberExtension with the integer value . * The criticality is set to false. * * @param crlNum the value to be set for the extension. */ public CRLNumberExtension(int crlNum) throws IOException { this.crlNumber = new BigInt(crlNum); this.extensionId = PKIXExtensions.CRLNumber_Id; this.critical = false; encodeThis(); } /** * Create a CRLNumberExtension with the BigInteger value . * The criticality is set to false. * * @param crlNum the value to be set for the extension. */ public CRLNumberExtension(BigInteger crlNum) throws IOException { this.crlNumber = new BigInt(crlNum); this.extensionId = PKIXExtensions.CRLNumber_Id; this.critical = false; encodeThis(); } /** * Create a CRLNumberExtension with the BigInteger value . * * @param critical true if the extension is to be treated as critical. * @param crlNum the value to be set for the extension. */ public CRLNumberExtension(Boolean critical, BigInteger crlNum) throws IOException { this.crlNumber = new BigInt(crlNum); this.extensionId = PKIXExtensions.CRLNumber_Id; this.critical = critical.booleanValue(); encodeThis(); } /** * Create the extension from the passed DER encoded value of the same. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public CRLNumberExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.CRLNumber_Id; this.critical = critical.booleanValue(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); this.crlNumber = val.getInteger(); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { if (name.equalsIgnoreCase(NUMBER)) { if (!(obj instanceof BigInteger)) { throw new IOException("Attribute must be of type BigInteger."); } crlNumber = new BigInt((BigInteger) obj); } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:CRLNumber."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(NUMBER)) { if (crlNumber == null) return null; else return crlNumber.toBigInteger(); } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:CRLNumber."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(NUMBER)) { crlNumber = null; } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:CRLNumber."); } } /** * Returns a printable representation of the CRLNumberExtension. */ @Override public String toString() { String s = super.toString() + "CRL Number: " + ((crlNumber == null) ? "" : crlNumber.toString()) + "\n"; return (s); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { this.extensionId = PKIXExtensions.CRLNumber_Id; this.critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(NUMBER); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CRLReasonExtension.java000066400000000000000000000175321412550063600305240ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * Represent the CRLReason Extension of CRL entry. * *

* This extension, if present, defines the identifies the reason for the certificate revocation. * * @author galperin * @version $Revision$, $Date$ * @see Extension * @see CertAttrSet */ public final class CRLReasonExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 4544973296866779535L; /** * Canned instances for all revocation reasons */ public static final CRLReasonExtension UNSPECIFIED = new CRLReasonExtension(RevocationReason.UNSPECIFIED); public static final CRLReasonExtension KEY_COMPROMISE = new CRLReasonExtension(RevocationReason.KEY_COMPROMISE); public static final CRLReasonExtension CA_COMPROMISE = new CRLReasonExtension(RevocationReason.CA_COMPROMISE); public static final CRLReasonExtension AFFILIATION_CHANGED = new CRLReasonExtension( RevocationReason.AFFILIATION_CHANGED); public static final CRLReasonExtension SUPERSEDED = new CRLReasonExtension(RevocationReason.SUPERSEDED); public static final CRLReasonExtension CESSATION_OF_OPERATION = new CRLReasonExtension( RevocationReason.CESSATION_OF_OPERATION); public static final CRLReasonExtension CERTIFICATE_HOLD = new CRLReasonExtension(RevocationReason.CERTIFICATE_HOLD); public static final CRLReasonExtension REMOVE_FROM_CRL = new CRLReasonExtension(RevocationReason.REMOVE_FROM_CRL); public static final CRLReasonExtension PRIVILEGE_WITHDRAWN = new CRLReasonExtension( RevocationReason.PRIVILEGE_WITHDRAWN); public static final CRLReasonExtension AA_COMPROMISE = new CRLReasonExtension(RevocationReason.AA_COMPROMISE); /** * Attribute names. */ public static final String NAME = "CRLReason"; public static final String REASON = "value"; private RevocationReason mReason = null; public RevocationReason getReason() { return mReason; } /** * Default constructor * */ public CRLReasonExtension() { this.extensionId = PKIXExtensions.ReasonCode_Id; this.critical = false; mReason = null; } /** * Create extension value for specific revocation reason * */ public CRLReasonExtension(RevocationReason reason) { this.extensionId = PKIXExtensions.ReasonCode_Id; this.critical = false; mReason = reason; } public CRLReasonExtension(Boolean critical, RevocationReason reason) throws IOException { this.extensionId = PKIXExtensions.ReasonCode_Id; this.critical = critical.booleanValue(); mReason = reason; } /** * Create the object from the passed DER encoded value. * * @param value the DerValue decoded from the stream. * @exception IOException on decoding errors. */ public CRLReasonExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.ReasonCode_Id; this.critical = critical.booleanValue(); byte[] extValue = ((byte[]) value).clone(); this.extensionValue = extValue; DerValue val = new DerValue(extValue); int reasonCode = val.getEnumerated(); mReason = RevocationReason.fromInt(reasonCode); if (mReason == null) throw new IOException("Unknown revocation reason value " + reasonCode); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { if (!(obj instanceof RevocationReason)) { throw new IOException("Attribute must be of type RevocationReason."); } if (name.equalsIgnoreCase(REASON)) { mReason = (RevocationReason) obj; } else { throw new IOException("Name not recognized by CRLReason"); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(REASON)) { return mReason; } else { throw new IOException("Name not recognized by CRLReason"); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(REASON)) { mReason = null; } else { throw new IOException("Name not recognized by CRLReason"); } } /** * Returns a printable representation of the ReasonFlags. */ @Override public String toString() { String s = super.toString() + "CRL Reason [" + mReason + "]\n"; return (s); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } // Encode this extension value private void encodeThis() throws IOException { if (mReason == null) throw new IOException("Unintialized CRLReason extension"); try (DerOutputStream os = new DerOutputStream()) { os.putEnumerated(mReason.toInt()); this.extensionValue = os.toByteArray(); } } /** * Write the extension to the DerOutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on encoding errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(REASON); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } @Override public boolean equals(Object other) { if (this == other) return true; else if (other instanceof CRLReasonExtension) return ((CRLReasonExtension) other).mReason == mReason && ((CRLReasonExtension) other).critical == critical; else return false; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((mReason == null) ? 0 : mReason.hashCode()); return result; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CertAndKeyGen.java000066400000000000000000000225611412550063600274600ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.security.InvalidKeyException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Date; import org.mozilla.jss.netscape.security.pkcs.PKCS10; /** * Generate a pair of keys, and provide access to them. This class is * provided primarily for ease of use. * *

* This provides some simple certificate management functionality. Specifically, it allows you to create self-signed * X.509 certificates as well as PKCS 10 based certificate signing requests. * *

* Keys for some public key signature algorithms have algorithm parameters, such as DSS/DSA. Some sites' Certificate * Authorities adopt fixed algorithm parameters, which speeds up some operations including key generation and signing. * At this time, this interface * does not provide a way to provide such algorithm parameters, e.g. * by providing the CA certificate which includes those parameters. * *

* Also, note that at this time only signature-capable keys may be acquired through this interface. Diffie-Hellman keys, * used for secure key exchange, may be supported later. * * @author David Brownell * @author Hemma Prafullchandra * @version 1.44 * @see PKCS10 * @see X509CertImpl */ public final class CertAndKeyGen { /** * Creates a CertAndKeyGen object for a particular key type * and signature algorithm. * * @param keyType type of key, e.g. "RSA", "DSA" * @param sigAlg name of the signature algorithm, e.g. "MD5WithRSA", * "MD2WithRSA", "SHAwithDSA". * @exception NoSuchAlgorithmException on unrecognized algorithms. */ public CertAndKeyGen(String keyType, String sigAlg) throws NoSuchAlgorithmException { keyGen = KeyPairGenerator.getInstance(keyType); this.sigAlg = sigAlg; } // want "public void generate (X509Certificate)" ... inherit DSA/D-H param /** * Generates a random public/private key pair, with a given key * size. Different algorithms provide different degrees of security * for the same key size, because of the "work factor" involved in * brute force attacks. As computers become faster, it becomes * easier to perform such attacks. Small keys are to be avoided. * *

* Note that not all values of "keyBits" are valid for all algorithms, and not all public key algorithms are * currently supported for use in X.509 certificates. If the algorithm you specified does not produce X.509 * compatible keys, an invalid key exception is thrown. * * @param keyBits the number of bits in the keys. * @exception InvalidKeyException if the environment does not * provide X.509 public keys for this signature algorithm. */ public void generate(int keyBits) throws InvalidKeyException { KeyPair pair; try { keyGen.initialize(keyBits); pair = keyGen.generateKeyPair(); } catch (Exception e) { throw new IllegalArgumentException(e.getMessage()); } PublicKey publicKey = pair.getPublic(); if (publicKey instanceof X509Key) { this.publicKey = (X509Key) publicKey; } else { throw new InvalidKeyException("public key " + publicKey + " not an X509Key."); } privateKey = pair.getPrivate(); } /** * Returns the public key of the generated key pair. */ public X509Key getPublicKey() { return publicKey; } /** * Returns the private key of the generated key pair. * *

* Be extremely careful when handling private keys. * When private keys are not kept secret, they lose their ability * to securely authenticate specific entities ... that is a huge * security risk! */ public PrivateKey getPrivateKey() { return privateKey; } /** * Returns a self-signed X.509v3 certificate for the public key. * The certificate is immediately valid. No extensions. * *

* Such certificates normally are used to identify a "Certificate Authority" (CA). Accordingly, they will not always * be accepted by other parties. However, such certificates are also useful when you are bootstrapping your security * infrastructure, or deploying system prototypes. * * @param myname X.500 name of the subject (who is also the issuer) * @param validity how long the certificate should be valid, in seconds * @exception CertificateException on certificate handling errors. * @exception InvalidKeyException on key handling errors. * @exception SignatureException on signature handling errors. * @exception NoSuchAlgorithmException on unrecognized algorithms. * @exception NoSuchProviderException on unrecognized providers. */ public X509Certificate getSelfCertificate(X500Name myname, long validity) throws CertificateException, InvalidKeyException, SignatureException, NoSuchAlgorithmException, NoSuchProviderException { X500Signer issuer; X509CertImpl cert; Date firstDate, lastDate; try { issuer = getSigner(myname); firstDate = new Date(); lastDate = new Date(); lastDate.setTime(lastDate.getTime() + validity * 1000); CertificateValidity interval = new CertificateValidity(firstDate, lastDate); X509CertInfo info = new X509CertInfo(); // Add all mandatory attributes info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V1)); info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber((int) (firstDate.getTime() / 1000))); AlgorithmId algID = issuer.getAlgorithmId(); info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(algID)); info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(myname)); info.set(X509CertInfo.KEY, new CertificateX509Key(publicKey)); info.set(X509CertInfo.VALIDITY, interval); info.set(X509CertInfo.ISSUER, new CertificateIssuerName(issuer.getSigner())); cert = new X509CertImpl(info); cert.sign(privateKey, algID.getName()); return cert; } catch (IOException e) { throw new CertificateEncodingException("getSelfCertificate: " + e.getMessage()); } } /** * Returns a PKCS #10 certificate request. The caller uses either PKCS10.print or * PKCS10.toByteArray operations on the result, to get the request in an appropriate * transmission format. * *

* PKCS #10 certificate requests are sent, along with some proof of identity, to Certificate Authorities (CAs) which * then issue X.509 public key certificates. * * @param myname X.500 name of the subject * @exception InvalidKeyException on key handling errors. * @exception SignatureException on signature handling errors. */ public PKCS10 getCertRequest(X500Name myname) throws InvalidKeyException, SignatureException { PKCS10 req = new PKCS10(publicKey); try { req.encodeAndSign(getSigner(myname)); } catch (CertificateException e) { throw new SignatureException(sigAlg + " CertificateException"); } catch (IOException e) { throw new SignatureException(sigAlg + " IOException"); } catch (NoSuchAlgorithmException e) { // "can't happen" throw new SignatureException(sigAlg + " unavailable?"); } return req; } private X500Signer getSigner(X500Name me) throws InvalidKeyException, NoSuchAlgorithmException { Signature signature = Signature.getInstance(sigAlg); signature.initSign(privateKey); return new X500Signer(signature, me); } private String sigAlg; private KeyPairGenerator keyGen; private X509Key publicKey; private PrivateKey privateKey; } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CertAttrSet.java000066400000000000000000000077211412550063600272420ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Enumeration; /** * This interface defines the methods required of a certificate attribute. * Examples of X.509 certificate attributes are Validity, Issuer_Name, and * Subject Name. A CertAttrSet may compromise one attribute or many * attributes. *

* A CertAttrSet itself can also be comprised of other sub-sets. In the case of X.509 V3 certificates, for example, the * "extensions" attribute has subattributes, such as those for KeyUsage and AuthorityKeyIdentifier. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.9 * @see CertificateException */ public interface CertAttrSet { /** * Returns a short string describing this certificate attribute. * * @return value of this certificate attribute in * printable form. */ @Override String toString(); /** * Encodes the attribute to the output stream in a format * that can be parsed by the decode method. * * @param out the OutputStream to encode the attribute to. * * @exception CertificateException on encoding or validity errors. * @exception IOException on other errors. */ void encode(OutputStream out) throws CertificateException, IOException; /** * Decodes the attribute in the input stream. * * @param in the InputStream to read the encoded attribute from. * * @exception CertificateException on decoding or validity errors. * @exception IOException on other errors. */ void decode(InputStream in) throws CertificateException, IOException; /** * Sets an attribute value within this CertAttrSet. * * @param name the name of the attribute (e.g. "x509.info.key") * @param obj the attribute object. * * @exception CertificateException on attribute handling errors. * @exception IOException on other errors. */ void set(String name, Object obj) throws CertificateException, IOException; /** * Gets an attribute value for this CertAttrSet. * * @param name the name of the attribute to return. * * @exception CertificateException on attribute handling errors. * @exception IOException on other errors. */ Object get(String name) throws CertificateException, IOException; /** * Deletes an attribute value from this CertAttrSet. * * @param name the name of the attribute to delete. * * @exception CertificateException on attribute handling errors. * @exception IOException on other errors. */ void delete(String name) throws CertificateException, IOException; /** * Returns an enumeration of the names of the attributes existing within * this attribute. * * @return an enumeration of the attribute names. */ Enumeration getAttributeNames(); /** * Returns the name (identifier) of this CertAttrSet. * * @return the name of this CertAttrSet. */ String getName(); } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CertException.java000066400000000000000000000125411412550063600276060ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; /** * CertException indicates one of a variety of certificate problems. * * @version 1.18 * * @author David Brownell * @author Amit Kapoor * @author Hemma Prafullchandra */ public class CertException extends SecurityException { // Zero is reserved. /** * */ private static final long serialVersionUID = -4046189948107720588L; /** Indicates that the signature in the certificate is not valid. */ public static final int verf_INVALID_SIG = 1; /** Indicates that the certificate was revoked, and so is invalid. */ public static final int verf_INVALID_REVOKED = 2; /** Indicates that the certificate is not yet valid. */ public static final int verf_INVALID_NOTBEFORE = 3; /** Indicates that the certificate has expired and so is not valid. */ public static final int verf_INVALID_EXPIRED = 4; /** * Indicates that a certificate authority in the certification * chain is not trusted. */ public static final int verf_CA_UNTRUSTED = 5; /** Indicates that the certification chain is too long. */ public static final int verf_CHAIN_LENGTH = 6; /** Indicates an error parsing the ASN.1/DER encoding of the certificate. */ public static final int verf_PARSE_ERROR = 7; /** Indicates an error constructing a certificate or certificate chain. */ public static final int err_CONSTRUCTION = 8; /** Indicates a problem with the public key */ public static final int err_INVALID_PUBLIC_KEY = 9; /** Indicates a problem with the certificate version */ public static final int err_INVALID_VERSION = 10; /** Indicates a problem with the certificate format */ public static final int err_INVALID_FORMAT = 11; /** Indicates a problem with the certificate encoding */ public static final int err_ENCODING = 12; // Private data members private int verfCode; private String moreData; /** * Constructs a certificate exception using an error code * (verf_*) and a string describing the context * of the error. */ public CertException(int code, String moredata) { verfCode = code; moreData = moredata; } /** * Constructs a certificate exception using just an error code, * without a string describing the context. */ public CertException(int code) { verfCode = code; } /** * Returns the error code with which the exception was created. */ public int getVerfCode() { return verfCode; } /** * Returns a string describing the context in which the exception * was reported. */ public String getMoreData() { return moreData; } /** * Return a string corresponding to the error code used to create * this exception. */ public String getVerfDescription() { switch (verfCode) { case verf_INVALID_SIG: return "The signature in the certificate is not valid."; case verf_INVALID_REVOKED: return "The certificate has been revoked."; case verf_INVALID_NOTBEFORE: return "The certificate is not yet valid."; case verf_INVALID_EXPIRED: return "The certificate has expired."; case verf_CA_UNTRUSTED: return "The Authority which issued the certificate is not trusted."; case verf_CHAIN_LENGTH: return "The certificate path to a trusted authority is too long."; case verf_PARSE_ERROR: return "The certificate could not be parsed."; case err_CONSTRUCTION: return "There was an error when constructing the certificate."; case err_INVALID_PUBLIC_KEY: return "The public key was not in the correct format."; case err_INVALID_VERSION: return "The certificate has an invalid version number."; case err_INVALID_FORMAT: return "The certificate has an invalid format."; case err_ENCODING: return "Problem encountered while encoding the data."; default: return "Unknown code: " + verfCode; } } /** * Returns a string describing the certificate exception. */ @Override public String toString() { return "[Certificate Exception: " + getMessage() + "]"; } /** * Returns a string describing the certificate exception. */ @Override public String getMessage() { return getVerfDescription() + ((moreData != null) ? ("\n (" + moreData + ")") : ""); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CertParseError.java000066400000000000000000000024661412550063600277410ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; //back out these changes until backwards compatibility with //CertException is not an issue. //import java.security.CertificateException; /** * CertException indicates one of a variety of certificate problems. * * @version 1.7 * @author David Brownell */ class CertParseError extends CertException { /** * */ private static final long serialVersionUID = -7623327377774730807L; CertParseError(String where) { super(CertException.verf_PARSE_ERROR, where); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateAlgorithmId.java000066400000000000000000000134141412550063600314000ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.Serializable; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class defines the AlgorithmId for the Certificate. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.7 */ public class CertificateAlgorithmId implements CertAttrSet, Serializable { /** * */ private static final long serialVersionUID = 6084780721443376563L; private AlgorithmId algId; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.algorithmID"; /** * Sub attributes name for this CertAttrSet. */ public static final String NAME = "algorithmID"; public static final String ALGORITHM = "algorithm"; /** * Default constructor for the certificate attribute. * * @param algId the Algorithm identifier */ public CertificateAlgorithmId(AlgorithmId algId) { this.algId = algId; } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the serial number from. * @exception IOException on decoding errors. */ public CertificateAlgorithmId(DerInputStream in) throws IOException { DerValue val = in.getDerValue(); algId = AlgorithmId.parse(val); } /** * Create the object, decoding the values from the passed stream. * * @param in the InputStream to read the serial number from. * @exception IOException on decoding errors. */ public CertificateAlgorithmId(InputStream in) throws IOException { DerValue val = new DerValue(in); algId = AlgorithmId.parse(val); } /** * Return the algorithm identifier as user readable string. */ @Override public String toString() { if (algId == null) return ""; return (algId.toString() + ", OID = " + (algId.getOID()).toString() + "\n"); } private void writeObject(ObjectOutputStream stream) throws IOException { encode(stream); } private void readObject(ObjectInputStream stream) throws IOException { decode(stream); } /** * Encode the algorithm identifier in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @exception IOException on errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); algId.encode(tmp); out.write(tmp.toByteArray()); } /** * Decode the algorithm identifier from the passed stream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on errors. */ @Override public void decode(InputStream in) throws IOException { DerValue derVal = new DerValue(in); algId = AlgorithmId.parse(derVal); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { if (!(obj instanceof AlgorithmId)) { throw new IOException("Attribute must be of type AlgorithmId."); } if (name.equalsIgnoreCase(ALGORITHM)) { algId = (AlgorithmId) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateAlgorithmId."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(ALGORITHM)) { return (algId); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateAlgorithmId."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(ALGORITHM)) { algId = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateAlgorithmId."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(ALGORITHM); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateChain.java000066400000000000000000000162201412550063600302150ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.io.Serializable; import java.io.StringWriter; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.mozilla.jss.netscape.security.pkcs.PKCS7; import org.mozilla.jss.netscape.security.util.Cert; import org.mozilla.jss.netscape.security.util.Utils; public class CertificateChain implements Serializable { private List certs = new ArrayList<>(); /** * Constructs an empty certificate chain. */ public CertificateChain() { } /** * constructs a certificate chain from a certificate. * * @param cert a certificate */ public CertificateChain(X509Certificate cert) { if (cert == null) { throw new IllegalArgumentException("Missing input certificate"); } certs.add(cert); } /** * constructs a certificate chain from a X509 certificate array. * * @param certs a certificate array. */ public CertificateChain(X509Certificate[] certs) { if (certs == null) { throw new IllegalArgumentException("Missing input certificates"); } this.certs.addAll(Arrays.asList(certs)); } /** * Returns the certificate list. * * @return The certificate list. */ public List getCertificates() { return certs; } /** * returns the certificate at specified index in chain. * * @param index the index. * @return the X509 certificate at the given index. */ public X509Certificate getCertificate(int index) { return certs.get(index); } /** * returns the first certificate in chain. * * @return the X509 certificate at the given index. */ public X509Certificate getFirstCertificate() { return certs.get(0); } /** * returns the certificate chain as an array of X509 certificates. * * @return an array of X509 Certificates. */ public X509Certificate[] getChain() { return certs.toArray(new X509Certificate[certs.size()]); } /** * Sorts certificate chain from root to leaf. */ public void sort() throws Exception { X509Certificate[] certs = getChain(); certs = Cert.sortCertificateChain(certs); this.certs.clear(); this.certs.addAll(Arrays.asList(certs)); } public void encode(OutputStream out) throws IOException { encode(out, true); } /** * encode in PKCS7 blob. */ public void encode(OutputStream out, boolean sort) throws IOException { X509Certificate[] certs = getChain(); PKCS7 p7 = new PKCS7(certs); p7.encodeSignedData(out, sort); } /** * decode from PKCS7 blob. */ public void decode(InputStream in) throws IOException { PKCS7 p7 = new PKCS7(in); certs.clear(); certs.addAll(Arrays.asList(p7.getCertificates())); } /** * for serialization */ private void writeObject(java.io.ObjectOutputStream out) throws IOException { encode(out); } /** * for serialization */ private void readObject(java.io.ObjectInputStream in) throws IOException { decode(in); } public void addCertificate(X509Certificate cert) { certs.add(cert); } public void addCertificateChain(CertificateChain certChain) { certs.addAll(certChain.certs); } public void addPKCS7(PKCS7 pkcs7) { certs.addAll(Arrays.asList(pkcs7.getCertificates())); } /** * Convert a series of PEM certificates or a PKCS #7 data into a certificate chain. * This method will only accept a single chain, so it cannot be used to load CA bundle. */ public static CertificateChain fromPEMString(String input) throws Exception { CertificateChain certChain = new CertificateChain(); StringBuilder sb = new StringBuilder(); String[] lines = input.split("\\r?\\n"); for (String line : lines) { line = line.trim(); if (Cert.HEADER.equals(line)) { sb.setLength(0); } else if (Cert.FOOTER.equals(line)) { byte[] bytes = Utils.base64decode(sb.toString()); certChain.addCertificate(new X509CertImpl(bytes)); } else if (PKCS7.HEADER.equals(line)) { sb.setLength(0); } else if (PKCS7.FOOTER.equals(line)) { byte[] bytes = Utils.base64decode(sb.toString()); PKCS7 pkcs7 = new PKCS7(bytes); certChain.addPKCS7(pkcs7); } else { sb.append(line); } } // sort and validate the certificate chain certChain.sort(); return certChain; } /** * Convert the certificate chain into a series of PEM certificates. */ public String toPEMString() throws Exception { // sort and validate the certificate chain sort(); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw, true); for (X509Certificate cert : certs) { pw.println(Cert.HEADER); pw.print(Utils.base64encodeMultiLine(cert.getEncoded())); pw.println(Cert.FOOTER); } return sw.toString(); } /** * Convert the certificate chain into a PKCS #7 object. */ public PKCS7 toPKCS7() throws Exception { // sort and validate the certificate chain sort(); // convert X509Certificate into X509CertImpl List certImpls = new ArrayList<>(); for (X509Certificate cert : certs) { certImpls.add(new X509CertImpl(cert.getEncoded())); } return new PKCS7(certImpls.toArray(new X509CertImpl[0])); } /** * Converts the certificate chain to a readable string. */ @Override public String toString() { if (certs.isEmpty()) { return "[]"; } StringBuilder sb = new StringBuilder(); sb.append("["); for (X509Certificate cert : certs) { sb.append(cert); } sb.append("]"); return sb.toString(); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateExtensions.java000066400000000000000000000231731412550063600313370ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.security.cert.CertificateException; import java.util.Collections; import java.util.Enumeration; import java.util.LinkedHashMap; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class defines the Extensions attribute for the Certificate. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.11 * @see CertAttrSet */ public class CertificateExtensions extends Vector implements CertAttrSet { /** * */ private static final long serialVersionUID = -7172635300185788849L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions"; /** * name */ public static final String NAME = "extensions"; private LinkedHashMap map; // Parse the encoded extension public void parseExtension(Extension ext) throws IOException { try { @SuppressWarnings("unchecked") Class extClass = (Class) OIDMap.getClass(ext.getExtensionId()); if (extClass == null) { // Unsupported extension map.put(ext.getExtensionId().toString(), ext); addElement(ext); return; } Class[] params = { Boolean.class, Object.class }; Constructor cons = extClass.getConstructor(params); byte[] extData = ext.getExtensionValue(); int extLen = extData.length; Object value = Array.newInstance(byte.class, extLen); for (int i = 0; i < extLen; i++) { Array.setByte(value, i, extData[i]); } Object[] passed = new Object[] { Boolean.valueOf(ext.isCritical()), value }; CertAttrSet certExt = cons.newInstance(passed); if (certExt != null && certExt.getName() != null) { map.put(certExt.getName(), (Extension) certExt); addElement((Extension) certExt); } } catch (NoSuchMethodException e) { throw new IOException(e); } catch (InvocationTargetException e) { Throwable t = e.getTargetException(); if (t instanceof IOException) { throw (IOException)t; } throw new IOException(t); } catch (Exception e) { throw new IOException(e); } } /** * Default constructor for the certificate attribute. */ public CertificateExtensions() { map = new LinkedHashMap(); } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the Extension from. * @exception IOException on decoding errors. */ public CertificateExtensions(DerInputStream in) throws IOException { map = new LinkedHashMap(); DerValue[] exts = in.getSequence(5); for (int i = 0; i < exts.length; i++) { Extension ext = new Extension(exts[i]); parseExtension(ext); } } /** * Decode the extensions from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { DerValue val = new DerValue(in); DerInputStream str = val.toDerInputStream(); map = new LinkedHashMap(); DerValue[] exts = str.getSequence(5); for (int i = 0; i < exts.length; i++) { Extension ext = new Extension(exts[i]); parseExtension(ext); } } /** * Decode the extensions from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ public void decodeEx(InputStream in) throws IOException { DerValue val = new DerValue(in); DerInputStream str = null; if (val.isConstructed() && val.isContextSpecific((byte) 3)) { str = val.data; } else { str = val.toDerInputStream(); } map = new LinkedHashMap(); DerValue[] exts = str.getSequence(5); for (int i = 0; i < exts.length; i++) { Extension ext = new Extension(exts[i]); parseExtension(ext); } } private void writeObject(ObjectOutputStream stream) throws CertificateException, IOException { encode(stream); } private void readObject(ObjectInputStream stream) throws CertificateException, IOException { decodeEx(stream); } /** * Encode the extensions in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @exception CertificateException on encoding errors. * @exception IOException on errors. */ @Override public void encode(OutputStream out) throws CertificateException, IOException { try (DerOutputStream tmp = new DerOutputStream()) { DerOutputStream extOut = new DerOutputStream(); for (int i = 0; i < size(); i++) { Object thisOne = elementAt(i); if (thisOne instanceof CertAttrSet) ((CertAttrSet) thisOne).encode(extOut); else if (thisOne instanceof Extension) ((Extension) thisOne).encode(extOut); else throw new CertificateException("Invalid extension object"); } DerOutputStream seq = new DerOutputStream(); seq.write(DerValue.tag_Sequence, extOut); tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 3), seq); out.write(tmp.toByteArray()); } } /** * Set the attribute value. * * @param name the extension name used in the cache. * @param obj the object to set. * @exception IOException if the object could not be cached. */ @Override public void set(String name, Object obj) throws IOException { map.put(name, (Extension) obj); addElement((Extension) obj); } /** * Get the attribute value. * * @param name the extension name used in the lookup. * @exception IOException if named extension is not found. */ @Override public Object get(String name) throws IOException { Object obj = map.get(name); if (obj == null) { throw new IOException("No extension found with name " + name); } return (obj); } /** * Delete the attribute value. * * @param name the extension name used in the lookup. * @exception IOException if named extension is not found. */ @Override public void delete(String name) throws IOException { Object obj = map.get(name); if (obj == null) { throw new IOException("No extension found with name " + name); } map.remove(name); removeElement(obj); } public Enumeration getNames() { return Collections.enumeration(map.keySet()); } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getAttributes() { return Collections.enumeration(map.values()); } @Override public Enumeration getAttributeNames() { return getNames(); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((map == null) ? 0 : map.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; CertificateExtensions other = (CertificateExtensions) obj; if (map == null) { if (other.map != null) return false; } else if (!map.equals(other.map)) return false; return true; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateIssuerExtension.java000066400000000000000000000171741412550063600323530ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * Represent the CRL Certificate Issuer Extension. * *

* This CRL entry extension identifies the certificate issuer associated with an entry in an indirect CRL, i.e. a CRL * that has the indirectCRL indicator set in its issuing distribution point extension. * * @see Extension * @see CertAttrSet */ public class CertificateIssuerExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 8643788952936025986L; /** * Attribute name. */ public static final String NAME = "CertificateIssuer"; public static final String CERTIFICATE_ISSUER = "value"; /** * The Object Identifier for this extension. */ public static final String OID = "2.5.29.29"; // private data members GeneralNames names = null; static { try { OIDMap.addAttribute(CertificateIssuerExtension.class.getName(), OID, NAME); } catch (CertificateException e) { } } // Encode this extension private void encodeThis() throws IOException { DerOutputStream os = new DerOutputStream(); try { names.encode(os); } catch (GeneralNamesException e) { throw new IOException(e); } this.extensionValue = os.toByteArray(); } /** * Create a CertificateIssuerExtension with the passed GeneralNames * and criticality. * * @param critical true if the extension is to be treated as critical. * @param names the GeneralNames for the issuer. * @exception IOException on error. */ public CertificateIssuerExtension(Boolean critical, GeneralNames names) throws IOException { this.names = names; this.extensionId = PKIXExtensions.CertificateIssuer_Id; this.critical = critical.booleanValue(); encodeThis(); } /** * Create a CertificateIssuerExtension with the passed GeneralNames. * * @param names the GeneralNames for the issuer. * @exception IOException on error. */ public CertificateIssuerExtension(GeneralNames names) throws IOException { this.names = names; this.extensionId = PKIXExtensions.CertificateIssuer_Id; this.critical = true; encodeThis(); } /** * Create a default CertificateIssuerExtension. */ public CertificateIssuerExtension() { extensionId = PKIXExtensions.CertificateIssuer_Id; critical = false; names = new GeneralNames(); } /** * Create the extension from the passed DER encoded value. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public CertificateIssuerExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.CertificateIssuer_Id; this.critical = critical.booleanValue(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); try { names = new GeneralNames(val); } catch (GeneralNamesException e) { throw new IOException("CertificateIssuerExtension: " + e, e); } } /** * Returns a printable representation of the CertificateIssuerName. */ @Override public String toString() { if (names == null) return ""; String s = super.toString() + "CertificateIssuerName [\n" + names.toString() + "]\n"; return (s); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the OutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on encoding error. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { extensionId = PKIXExtensions.CertificateIssuer_Id; critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { if (name.equalsIgnoreCase(CERTIFICATE_ISSUER)) { if (!(obj instanceof GeneralNames)) { throw new IOException("Attribute value should be of" + " type GeneralNames."); } names = (GeneralNames) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateIssuerName."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(CERTIFICATE_ISSUER)) { return (names); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateIssuerName."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(CERTIFICATE_ISSUER)) { names = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateIssuerName."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(CERTIFICATE_ISSUER); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateIssuerName.java000066400000000000000000000123171412550063600312510ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class defines the X500Name attribute for the Certificate. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.6 * @see CertAttrSet */ public class CertificateIssuerName implements CertAttrSet { /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.issuer"; /** * Sub attributes name for this CertAttrSet. */ public static final String NAME = "issuer"; public static final String DN_NAME = "dname"; // Private data member private X500Name dnName; /** * Default constructor for the certificate attribute. * * @param name the X500Name */ public CertificateIssuerName(X500Name name) { this.dnName = name; } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the X500Name from. * @exception IOException on decoding errors. */ public CertificateIssuerName(DerInputStream in) throws IOException { dnName = new X500Name(in); } /** * Create the object, decoding the values from the passed stream. * * @param in the InputStream to read the X500Name from. * @exception IOException on decoding errors. */ public CertificateIssuerName(InputStream in) throws IOException { DerValue derVal = new DerValue(in); dnName = new X500Name(derVal); } /** * Return the name as user readable string. */ @Override public String toString() { if (dnName == null) return ""; return (dnName.toString()); } /** * Encode the name in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @exception IOException on errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); dnName.encode(tmp); out.write(tmp.toByteArray()); } /** * Decode the name in DER form from the stream. * * @param in the InputStream to marshal the contents from. * @exception IOException on errors. */ @Override public void decode(InputStream in) throws IOException { DerValue derVal = new DerValue(in); dnName = new X500Name(derVal); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { if (!(obj instanceof X500Name)) { throw new IOException("Attribute must be of type X500Name."); } if (name.equalsIgnoreCase(DN_NAME)) { this.dnName = (X500Name) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateIssuerName."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(DN_NAME)) { return (dnName); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateIssuerName."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(DN_NAME)) { dnName = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateIssuerName."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(DN_NAME); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateIssuerUniqueIdentity.java000066400000000000000000000132231412550063600333460ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class defines the subject/issuer unique identity attribute * for the Certificate. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.6 * @see CertAttrSet */ public class CertificateIssuerUniqueIdentity implements CertAttrSet { private UniqueIdentity id; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.issuerID"; /** * Sub attributes name for this CertAttrSet. */ public static final String NAME = "issuerID"; public static final String ID = "id"; /** * Default constructor for the certificate attribute. * * @param id the UniqueIdentity */ public CertificateIssuerUniqueIdentity(UniqueIdentity id) { this.id = id; } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the UniqueIdentity from. * @exception IOException on decoding errors. */ public CertificateIssuerUniqueIdentity(DerInputStream in) throws IOException { id = new UniqueIdentity(in); } /** * Create the object, decoding the values from the passed stream. * * @param in the InputStream to read the UniqueIdentity from. * @exception IOException on decoding errors. */ public CertificateIssuerUniqueIdentity(InputStream in) throws IOException { DerValue val = new DerValue(in); id = new UniqueIdentity(val); } /** * Create the object, decoding the values from the passed DER value. * * @param val the DerValue to read the UniqueIdentity from. * @exception IOException on decoding errors. */ public CertificateIssuerUniqueIdentity(DerValue val) throws IOException { id = new UniqueIdentity(val); } /** * Return the identity as user readable string. */ @Override public String toString() { if (id == null) return ""; return (id.toString()); } /** * Decode the identity in DER form from the stream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on errors. */ @Override public void decode(InputStream in) throws IOException { DerValue val = new DerValue(in); id = new UniqueIdentity(val); } /** * Encode the identity in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @exception IOException on errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); id.encode(tmp, DerValue.createTag(DerValue.TAG_CONTEXT, false, (byte) 1)); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { if (!(obj instanceof UniqueIdentity)) { throw new IOException("Attribute must be of type UniqueIdentity."); } if (name.equalsIgnoreCase(ID)) { id = (UniqueIdentity) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateIssuerUniqueIdentity."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(ID)) { return (id); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateIssuerUniqueIdentity."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(ID)) { id = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateIssuerUniqueIdentity."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(ID); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CertificatePoliciesExtension.java000066400000000000000000000276521412550063600326520ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; import org.mozilla.jss.netscape.security.util.Utils; /** * This class defines the Certificate Policies Extension. * *

* The certificate policies extension conatins a sequence of policy information terms, each of which consists of an * object identifier (OID) and optional qualifiers. These policy information terms indicate the policy under which the * certificate has been issued and the purposes for which the certificate may be used. Aplications with specific policy * requirements are expected to have a list of those policies which they will accept and to compare the policy OIDs in * the certificate to that list. If this extension is critical, the path validation software must be able to interpret * this extension, or must reject the certificate. * *

 * CertificatePolicies ::= SEQUENECE OF PolicyInformation
 * 
* * @author Christine Ho * @see Extension * @see CertAttrSet */ public class CertificatePoliciesExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -3729294064061837367L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.CertificatePolicies"; /** * Attribute names. */ public static final String NAME = "CertificatePolicies"; public static final String INFOS = "infos"; // Private data members private Vector mInfos; // Encode this extension value private void encodeThis() throws IOException { try (DerOutputStream os = new DerOutputStream();) { DerOutputStream tmp = new DerOutputStream(); for (int i = 0; i < mInfos.size(); i++) { mInfos.elementAt(i).encode(tmp); } os.write(DerValue.tag_Sequence, tmp); extensionValue = os.toByteArray(); } } public CertificatePoliciesExtension(boolean critical, Vector infos) throws IOException { this.mInfos = infos; this.extensionId = PKIXExtensions.CertificatePolicies_Id; this.critical = critical; encodeThis(); } /** * Create a CertificatePolicies with the Vector of CertificatePolicyInfo. * * @param infos the Vector of CertificatePolicyInfo. */ public CertificatePoliciesExtension(Vector infos) throws IOException { this.mInfos = infos; this.extensionId = PKIXExtensions.CertificatePolicies_Id; this.critical = false; encodeThis(); } /** * Create a default CertificatePoliciesExtension. */ public CertificatePoliciesExtension() { this.extensionId = PKIXExtensions.CertificatePolicies_Id; critical = false; mInfos = new Vector(1, 1); } /** * Create the extension from the passed DER encoded value. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public CertificatePoliciesExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.CertificatePolicies_Id; this.critical = critical.booleanValue(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for " + "CertificatePoliciesExtension."); } mInfos = new Vector(1, 1); while (val.data.available() != 0) { DerValue seq = val.data.getDerValue(); CertificatePolicyInfo info = new CertificatePolicyInfo(seq); mInfos.addElement(info); } } /** * Returns a printable representation of the policy extension. */ @Override public String toString() { if (mInfos == null) return ""; String s = super.toString() + "Certificate Policies [\n" + mInfos.toString() + "]\n"; return (s); } /** * Write the extension to the OutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on encoding errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { extensionId = PKIXExtensions.CertificatePolicies_Id; critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Set the attribute value. */ @Override @SuppressWarnings("unchecked") public void set(String name, Object obj) throws IOException { clearValue(); if (name.equalsIgnoreCase(INFOS)) { if (!(obj instanceof Vector)) { throw new IOException("Attribute value should be of" + " type Vector."); } mInfos = (Vector) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificatePoliciesExtension."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(INFOS)) { return (mInfos); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificatePoliciesExtension."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(INFOS)) { mInfos = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificatePoliciesExtension."); } } /** * Return an enumeration of attributes existing within this * attribute. */ public Enumeration> getAttributes() { Vector> elements = new Vector>(); elements.addElement(mInfos); return (elements.elements()); } private static final String[] NAMES = { INFOS }; @Override public Enumeration getAttributeNames() { // TODO Auto-generated method stub return Collections.enumeration(Arrays.asList(NAMES)); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } public static void main(String args[]) { /** * From ASN.1 dump * * 0 30 133: SEQUENCE { * 3 30 45: . SEQUENCE { * 5 06 3: . . OBJECT IDENTIFIER '1 2 3 5' * 10 30 38: . . SEQUENCE { * 12 30 36: . . . SEQUENCE { * 14 06 8: . . . . OBJECT IDENTIFIER cps (1 3 6 1 5 5 7 2 1) * : . . . . . (PKIX policy qualifier) * 24 16 24: . . . . IA5String 'http://home.netscape.com' * : . . . . } * : . . . } * : . . } * 50 30 84: . SEQUENCE { * 52 06 2: . . OBJECT IDENTIFIER '2 3 5' * 56 30 78: . . SEQUENCE { * 58 30 36: . . . SEQUENCE { * 60 06 8: . . . . OBJECT IDENTIFIER cps (1 3 6 1 5 5 7 2 1) * : . . . . . (PKIX policy qualifier) * 70 16 24: . . . . IA5String 'http://home.netscape.com' * : . . . . } * 96 30 38: . . . SEQUENCE { * 98 06 8: . . . . OBJECT IDENTIFIER unotice (1 3 6 1 5 5 7 2 2) * : . . . . . (PKIX policy qualifier) * 108 30 26: . . . . SEQUENCE { * 110 30 16: . . . . . SEQUENCE { * 112 1E 8: . . . . . . BMPString (1993) '_..o.r.g' * 122 02 1: . . . . . . INTEGER 1 * 125 02 1: . . . . . . INTEGER 2 * : . . . . . . } * 128 1E 6: . . . . . BMPString (1993) '_..d.t' * : . . . . . } * : . . . . } * : . . . } * : . . } * : . } **/ CertificatePolicyId plcyId0 = new CertificatePolicyId( new ObjectIdentifier("1.2.3.5") ); PolicyQualifiers qualifiers0 = new PolicyQualifiers(); CPSuri cpsQualifier0 = new CPSuri("http://home.netscape.com"); PolicyQualifierInfo qualifierInfo0 = new PolicyQualifierInfo( PolicyQualifierInfo.QT_CPS, cpsQualifier0 ); qualifiers0.add(qualifierInfo0); CertificatePolicyInfo info0 = new CertificatePolicyInfo( plcyId0, qualifiers0); CertificatePolicyId plcyId1 = new CertificatePolicyId( new ObjectIdentifier("2.3.5") ); PolicyQualifiers qualifiers1 = new PolicyQualifiers(); DisplayText org1 = new DisplayText(DisplayText.tag_BMPString, "org"); int nums[] = { 1, 2 }; NoticeReference nr1 = new NoticeReference(org1, nums); DisplayText dt1 = new DisplayText(DisplayText.tag_BMPString, "dt"); UserNotice userNotice1 = new UserNotice(nr1, dt1); PolicyQualifierInfo qualifierInfo1 = new PolicyQualifierInfo( PolicyQualifierInfo.QT_UNOTICE, userNotice1 ); qualifiers1.add(qualifierInfo0); qualifiers1.add(qualifierInfo1); CertificatePolicyInfo info1 = new CertificatePolicyInfo( plcyId1, qualifiers1); Vector infos = new Vector(); infos.addElement(info0); infos.addElement(info1); try { CertificatePoliciesExtension ext = new CertificatePoliciesExtension(infos); // BASE64 encode the whole thing and write it to stdout System.out.println(Utils.base64encode(ext.getExtensionValue(), true)); } catch (IOException e) { System.out.println(e.toString()); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CertificatePolicyId.java000066400000000000000000000047641412550063600307210ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** * Represent the CertificatePolicyId ASN.1 object. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.5 */ public class CertificatePolicyId implements java.io.Serializable { /** * */ private static final long serialVersionUID = -2376810529862707757L; private ObjectIdentifier id; /** * Create a CertificatePolicyId with the ObjectIdentifier. * * @param id the ObjectIdentifier for the policy id. */ public CertificatePolicyId(ObjectIdentifier id) { this.id = id; } /** * Create the object from its Der encoded value. * * @param val the DER encoded value for the same. */ public CertificatePolicyId(DerValue val) throws IOException { this.id = val.getOID(); } /** * Return the value of the CertificatePolicyId as an ObjectIdentifier. */ public ObjectIdentifier getIdentifier() { return (id); } /** * Returns a printable representation of the CertificatePolicyId. */ @Override public String toString() { String s = "CertificatePolicyId: [" + id.toString() + "]\n"; return (s); } /** * Write the CertificatePolicyId to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException on errors. */ public void encode(DerOutputStream out) throws IOException { out.putOID(id); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CertificatePolicyInfo.java000066400000000000000000000070661412550063600312560ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * Represent the CertificatePolicyInformation ASN.1 object. * * @author Christine Ho */ public class CertificatePolicyInfo implements java.io.Serializable { /** * */ private static final long serialVersionUID = -8516006396099280477L; private CertificatePolicyId mPolicyIdentifier; private PolicyQualifiers mPolicyQualifiers; /** * Create a CertificatePolicyInfo with the passed CertificatePolicyId's. * * @param id the CertificatePolicyId. */ public CertificatePolicyInfo(CertificatePolicyId id) { this.mPolicyIdentifier = id; this.mPolicyQualifiers = null; } public CertificatePolicyInfo(CertificatePolicyId id, PolicyQualifiers qualifiers) { this.mPolicyIdentifier = id; this.mPolicyQualifiers = qualifiers; } /** * Create the CertificatePolicyInfo from the DER encoded value. * * @param val the DER encoded value of the same. */ public CertificatePolicyInfo(DerValue val) throws IOException { if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for CertificatePolicyInfo"); } mPolicyIdentifier = new CertificatePolicyId(val.data.getDerValue()); // The specification is not clear on whether qualifier is // optional or not. GTE CyberTrust Root certificate has // no qualifier. if (val.data.available() == 0) { mPolicyQualifiers = null; } else { mPolicyQualifiers = new PolicyQualifiers(val.data.getDerValue()); } } /** * return the policy identifier of the policy info */ public CertificatePolicyId getPolicyIdentifier() { return (mPolicyIdentifier); } public PolicyQualifiers getPolicyQualifiers() { return mPolicyQualifiers; } /** * Returns a printable representation of the CertificatePolicyId. */ @Override public String toString() { String s = "CertificatePolicyInfo: [\n" + "PolicyIdentifier:" + mPolicyIdentifier.toString() + "]\n"; return (s); } /** * Write the CertificatePolicyInfo to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException on errors. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); mPolicyIdentifier.encode(tmp); if (mPolicyQualifiers != null) { mPolicyQualifiers.encode(tmp); } out.write(DerValue.tag_Sequence, tmp); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CertificatePolicyMap.java000066400000000000000000000063341412550063600310750ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * Represent the CertificatePolicyMap ASN.1 object. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.5 */ public class CertificatePolicyMap { private CertificatePolicyId issuerDomain; private CertificatePolicyId subjectDomain; /** * Create a CertificatePolicyMap with the passed CertificatePolicyId's. * * @param issuer the CertificatePolicyId for the issuer CA. * @param subject the CertificatePolicyId for the subject CA. */ public CertificatePolicyMap(CertificatePolicyId issuer, CertificatePolicyId subject) { this.issuerDomain = issuer; this.subjectDomain = subject; } /** * Create the CertificatePolicyMap from the DER encoded value. * * @param val the DER encoded value of the same. */ public CertificatePolicyMap(DerValue val) throws IOException { if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for CertificatePolicyMap"); } issuerDomain = new CertificatePolicyId(val.data.getDerValue()); subjectDomain = new CertificatePolicyId(val.data.getDerValue()); } /** * Return the issuer CA part of the policy map. */ public CertificatePolicyId getIssuerIdentifier() { return (issuerDomain); } /** * Return the subject CA part of the policy map. */ public CertificatePolicyId getSubjectIdentifier() { return (subjectDomain); } /** * Returns a printable representation of the CertificatePolicyId. */ @Override public String toString() { String s = "CertificatePolicyMap: [\n" + "IssuerDomain:" + issuerDomain.toString() + "SubjectDomain:" + subjectDomain.toString() + "]\n"; return (s); } /** * Write the CertificatePolicyMap to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException on errors. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); issuerDomain.encode(tmp); subjectDomain.encode(tmp); out.write(DerValue.tag_Sequence, tmp); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CertificatePolicySet.java000066400000000000000000000051521412550063600311100ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class defines the certificate policy set ASN.1 object. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.4 */ public class CertificatePolicySet { private Vector ids; /** * The default constructor for this class. * * @param ids the sequence of CertificatePolicyId's. */ public CertificatePolicySet(Vector ids) { this.ids = ids; } /** * Create the object from the DerValue. * * @param in the passed DerInputStream. * @exception IOException on decoding errors. */ public CertificatePolicySet(DerInputStream in) throws IOException { ids = new Vector(1, 1); DerValue[] seq = in.getSequence(5); for (int i = 0; i < seq.length; i++) { CertificatePolicyId id = new CertificatePolicyId(seq[i]); ids.addElement(id); } } /** * Return printable form of the object. */ @Override public String toString() { String s = "CertificatePolicySet:[\n" + ids.toString() + "]\n"; return (s); } /** * Encode the policy set to the output stream. * * @param out the DerOutputStream to encode the data to. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); for (int i = 0; i < ids.size(); i++) { ids.elementAt(i).encode(tmp); } out.write(DerValue.tag_Sequence, tmp); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateSerialNumber.java000066400000000000000000000134701412550063600315670ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigInteger; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class defines the SerialNumber attribute for the Certificate. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.6 * @see CertAttrSet */ public class CertificateSerialNumber implements CertAttrSet { /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.serialNumber"; /** * Sub attributes name for this CertAttrSet. */ public static final String NAME = "serialNumber"; public static final String NUMBER = "number"; private SerialNumber serial; /** * Default constructor for the certificate attribute. * * @param num the serial number for the certificate. */ public CertificateSerialNumber(BigInteger num) { this.serial = new SerialNumber(num); } /** * Default constructor for the certificate attribute. * * @param num the serial number for the certificate. */ public CertificateSerialNumber(int num) { this.serial = new SerialNumber(num); } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the serial number from. * @exception IOException on decoding errors. */ public CertificateSerialNumber(DerInputStream in) throws IOException { serial = new SerialNumber(in); } /** * Create the object, decoding the values from the passed stream. * * @param in the InputStream to read the serial number from. * @exception IOException on decoding errors. */ public CertificateSerialNumber(InputStream in) throws IOException { serial = new SerialNumber(in); } /** * Create the object, decoding the values from the passed DerValue. * * @param val the DER encoded value. * @exception IOException on decoding errors. */ public CertificateSerialNumber(DerValue val) throws IOException { serial = new SerialNumber(val); } /** * Return the serial number as user readable string. */ @Override public String toString() { if (serial == null) return ""; return (serial.toString()); } /** * Encode the serial number in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @exception IOException on errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); serial.encode(tmp); out.write(tmp.toByteArray()); } /** * Decode the serial number in DER form from the stream. * * @param in the InputStream to marshal the contents from. * @exception IOException on errors. */ @Override public void decode(InputStream in) throws IOException { DerValue derVal = new DerValue(in); serial = new SerialNumber(derVal); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { if (!(obj instanceof SerialNumber)) { throw new IOException("Attribute must be of type SerialNumber."); } if (name.equalsIgnoreCase(NUMBER)) { serial = (SerialNumber) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateSerialNumber."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(NUMBER)) { return (serial); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateSerialNumber."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(NUMBER)) { serial = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateSerialNumber."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(NUMBER); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateSubjectName.java000066400000000000000000000144051412550063600313760ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.Serializable; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class defines the X500Name attribute for the Certificate. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.6 * @see CertAttrSet */ public class CertificateSubjectName implements CertAttrSet, Serializable { /** * */ private static final long serialVersionUID = 503643453152834350L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.subject"; /** * Sub attributes name for this CertAttrSet. */ public static final String NAME = "subject"; public static final String DN_NAME = "dname"; // Private data member private X500Name dnName; /** * Default constructor for the certificate attribute. * * @param name the X500Name */ public CertificateSubjectName(X500Name name) { this.dnName = name; } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the X500Name from. * @exception IOException on decoding errors. */ public CertificateSubjectName(DerInputStream in) throws IOException { dnName = new X500Name(in); } /** * Create the object, decoding the values from the passed stream. * * @param in the InputStream to read the X500Name from. * @exception IOException on decoding errors. */ public CertificateSubjectName(InputStream in) throws IOException { DerValue derVal = new DerValue(in); dnName = new X500Name(derVal); } /** * Return the name as user readable string. */ @Override public String toString() { if (dnName == null) return ""; return (dnName.toString()); } private void writeObject(ObjectOutputStream stream) throws IOException { encode(stream); } private void readObject(ObjectInputStream stream) throws IOException { decodeEx(stream); } /** * Encode the name in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @exception IOException on errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); dnName.encode(tmp); out.write(tmp.toByteArray()); } /** * Decode the name in DER form from the stream. * * @param in the InputStream to marshal the contents from. * @exception IOException on errors. */ public void decodeEx(InputStream in) throws IOException { DerValue derVal = new DerValue(in); // dnName = new X500Name(derVal); dnName = new X500Name(derVal.toByteArray()); } /** * Decode the name in DER form from the stream. * * @param in the InputStream to marshal the contents from. * @exception IOException on errors. */ @Override public void decode(InputStream in) throws IOException { DerValue derVal = new DerValue(in); dnName = new X500Name(derVal); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { if (!(obj instanceof X500Name)) { throw new IOException("Attribute must be of type X500Name."); } if (name.equalsIgnoreCase(DN_NAME)) { this.dnName = (X500Name) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateSubjectName."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(DN_NAME)) { return (dnName); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateSubjectName."); } } /** * Get underlying X500Name value. * * Where the type is known to be CertificateSubjectName, use * this method instead of 'get' to avoid casts and exceptions. */ public X500Name getX500Name() { return dnName; } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(DN_NAME)) { dnName = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:CertificateSubjectName."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(DN_NAME); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateSubjectUniqueIdentity.java000066400000000000000000000132351412550063600334760ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class defines the subject/issuer unique identity attribute * for the Certificate. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.6 * @see CertAttrSet */ public class CertificateSubjectUniqueIdentity implements CertAttrSet { /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.subjectID"; /** * Sub attributes name for this CertAttrSet. */ public static final String NAME = "subjectID"; public static final String ID = "id"; private UniqueIdentity id; /** * Default constructor for the certificate attribute. * * @param id the UniqueIdentity */ public CertificateSubjectUniqueIdentity(UniqueIdentity id) { this.id = id; } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the UniqueIdentity from. * @exception IOException on decoding errors. */ public CertificateSubjectUniqueIdentity(DerInputStream in) throws IOException { id = new UniqueIdentity(in); } /** * Create the object, decoding the values from the passed stream. * * @param in the InputStream to read the UniqueIdentity from. * @exception IOException on decoding errors. */ public CertificateSubjectUniqueIdentity(InputStream in) throws IOException { DerValue val = new DerValue(in); id = new UniqueIdentity(val); } /** * Create the object, decoding the values from the passed DER value. * * @param val the DerValue to read the UniqueIdentity from. * @exception IOException on decoding errors. */ public CertificateSubjectUniqueIdentity(DerValue val) throws IOException { id = new UniqueIdentity(val); } /** * Return the identity as user readable string. */ @Override public String toString() { if (id == null) return ""; return (id.toString()); } /** * Decode the identity in DER form from the stream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on errors. */ @Override public void decode(InputStream in) throws IOException { DerValue val = new DerValue(in); id = new UniqueIdentity(val); } /** * Encode the identity in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @exception IOException on errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); id.encode(tmp, DerValue.createTag(DerValue.TAG_CONTEXT, false, (byte) 2)); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { if (!(obj instanceof UniqueIdentity)) { throw new IOException("Attribute must be of type UniqueIdentity."); } if (name.equalsIgnoreCase(ID)) { id = (UniqueIdentity) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateSubjectUniqueIdentity."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(ID)) { return (id); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateSubjectUniqueIdentity."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(ID)) { id = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateSubjectUniqueIdentity."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(ID); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateValidity.java000066400000000000000000000244421412550063600307650ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.Serializable; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateNotYetValidException; import java.util.Date; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class defines the interval for which the certificate is valid. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.12 * @see CertAttrSet */ public class CertificateValidity implements CertAttrSet, Serializable { private static final long serialVersionUID = 8277703278213804194L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.validity"; /** * Sub attributes name for this CertAttrSet. */ public static final String NAME = "validity"; public static final String NOT_BEFORE = "notBefore"; public static final String NOT_AFTER = "notAfter"; private static final long YR_2050 = 2524636800000L; // Private data members private Date notBefore; private Date notAfter; // Returns the first time the certificate is valid. private Date getNotBefore() { return (new Date(notBefore.getTime())); } // Returns the last time the certificate is valid. private Date getNotAfter() { return (new Date(notAfter.getTime())); } // Construct the class from the DerValue private void construct(DerValue derVal) throws IOException { if (derVal.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoded CertificateValidity, " + "starting sequence tag missing."); } // check if UTCTime encoded or GeneralizedTime if (derVal.data.available() == 0) throw new IOException("No data encoded for CertificateValidity"); DerInputStream derIn = new DerInputStream(derVal.toByteArray()); DerValue[] seq = derIn.getSequence(2); if (seq.length != 2) throw new IOException("Invalid encoding for CertificateValidity"); if (seq[0].tag == DerValue.tag_UtcTime) { notBefore = derVal.data.getUTCTime(); } else if (seq[0].tag == DerValue.tag_GeneralizedTime) { notBefore = derVal.data.getGeneralizedTime(); } else { throw new IOException("Invalid encoding for CertificateValidity"); } if (seq[1].tag == DerValue.tag_UtcTime) { notAfter = derVal.data.getUTCTime(); } else if (seq[1].tag == DerValue.tag_GeneralizedTime) { notAfter = derVal.data.getGeneralizedTime(); } else { throw new IOException("Invalid encoding for CertificateValidity"); } } /** * Default constructor for the class. */ public CertificateValidity() { } /** * The default constructor for this class for the specified interval. * * @param notBefore the date and time before which the certificate * is not valid. * @param notAfter the date and time after which the certificate is * not valid. */ public CertificateValidity(Date notBefore, Date notAfter) { this.notBefore = notBefore; this.notAfter = notAfter; } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the CertificateValidity from. * @exception IOException on decoding errors. */ public CertificateValidity(DerInputStream in) throws IOException { DerValue derVal = in.getDerValue(); construct(derVal); } /** * Return the validity period as user readable string. */ @Override public String toString() { if (notBefore == null || notAfter == null) return ""; return ("Validity: [From: " + notBefore.toString() + ",\n To: " + notAfter.toString() + "]"); } /** * Decode the CertificateValidity period from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on errors. */ @Override public void decode(InputStream in) throws IOException { DerValue derVal = new DerValue(in); construct(derVal); } private void writeObject(ObjectOutputStream stream) throws IOException { encode(stream); } private void readObject(ObjectInputStream stream) throws IOException { decode(stream); } /** * Encode the CertificateValidity period in DER form to the stream. * * @param out the OutputStream to marshal the contents to. * @exception IOException on errors. */ @Override public void encode(OutputStream out) throws IOException { // in cases where default constructor is used check for // null values if (notBefore == null || notAfter == null) { throw new IOException("CertAttrSet:CertificateValidity:" + " null values to encode.\n"); } try (DerOutputStream pair = new DerOutputStream(); DerOutputStream seq = new DerOutputStream()) { if (notBefore.getTime() < YR_2050) { pair.putUTCTime(notBefore); } else pair.putGeneralizedTime(notBefore); if (notAfter.getTime() < YR_2050) { pair.putUTCTime(notAfter); } else { pair.putGeneralizedTime(notAfter); } seq.write(DerValue.tag_Sequence, pair); out.write(seq.toByteArray()); } } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { if (!(obj instanceof Date)) { throw new IOException("Attribute must be of type Date."); } if (name.equalsIgnoreCase(NOT_BEFORE)) { notBefore = (Date) obj; } else if (name.equalsIgnoreCase(NOT_AFTER)) { notAfter = (Date) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateValidity."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(NOT_BEFORE)) { return (getNotBefore()); } else if (name.equalsIgnoreCase(NOT_AFTER)) { return (getNotAfter()); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateValidity."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(NOT_BEFORE)) { notBefore = null; } else if (name.equalsIgnoreCase(NOT_AFTER)) { notAfter = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateValidity."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(NOT_BEFORE); elements.addElement(NOT_AFTER); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } /** * Verify that the current time is within the validity period. * * @exception CertificateExpiredException if the certificate has expired. * @exception CertificateNotYetValidException if the certificate is not * yet valid. */ public void valid() throws CertificateNotYetValidException, CertificateExpiredException { Date now = new Date(); valid(now); } /** * Verify that the passed time is within the validity period. * * @param now the Date against which to compare the validity * period. * * @exception CertificateExpiredException if the certificate has expired * with respect to the Date supplied. * @exception CertificateNotYetValidException if the certificate is not * yet valid with respect to the Date supplied. * */ public void valid(Date now) throws CertificateNotYetValidException, CertificateExpiredException { /* * we use the internal Dates rather than the passed in Date * because someone could override the Date methods after() * and before() to do something entirely different. */ if (notBefore.after(now)) { throw new CertificateNotYetValidException("NotBefore: " + notBefore.toString()); } if (notAfter.before(now)) { throw new CertificateExpiredException("NotAfter: " + notAfter.toString()); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateVersion.java000066400000000000000000000165461412550063600306330ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class defines the version of the X509 Certificate. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.8 * @see CertAttrSet */ public class CertificateVersion implements CertAttrSet { /** * X509Certificate Version 1 */ public static final int V1 = 0; /** * X509Certificate Version 2 */ public static final int V2 = 1; /** * X509Certificate Version 3 */ public static final int V3 = 2; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.version"; /** * Sub attributes name for this CertAttrSet. */ public static final String NAME = "version"; public static final String VERSION = "number"; // Private data members int version = V1; // Returns the version number. private int getVersion() { return (version); } // Construct the class from the passed DerValue private void construct(DerValue derVal) throws IOException { if (derVal.isConstructed() && derVal.isContextSpecific()) { derVal = derVal.data.getDerValue(); version = derVal.getInteger().toInt(); if (derVal.data.available() != 0) { throw new IOException("X.509 version, bad format"); } } } /** * The default constructor for this class, * sets the version to 0 (i.e. X.509 version 1). */ public CertificateVersion() { version = V1; } /** * The constructor for this class for the required version. * * @param version the version for the certificate. * @exception IOException if the version is not valid. */ public CertificateVersion(int version) throws IOException { // check that it is a valid version if (version == V1 || version == V2 || version == V3) this.version = version; else { throw new IOException("X.509 Certificate version " + version + " not supported.\n"); } } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the CertificateVersion from. * @exception IOException on decoding errors. */ public CertificateVersion(DerInputStream in) throws IOException { version = V1; DerValue derVal = in.getDerValue(); construct(derVal); } /** * Create the object, decoding the values from the passed stream. * * @param in the InputStream to read the CertificateVersion from. * @exception IOException on decoding errors. */ public CertificateVersion(InputStream in) throws IOException { version = V1; DerValue derVal = new DerValue(in); construct(derVal); } /** * Create the object, decoding the values from the passed DerValue. * * @param val the Der encoded value. * @exception IOException on decoding errors. */ public CertificateVersion(DerValue val) throws IOException { version = V1; construct(val); } /** * Return the version number of the certificate. */ @Override public String toString() { return ("Version: V" + (version + 1)); } /** * Encode the CertificateVersion period in DER form to the stream. * * @param out the OutputStream to marshal the contents to. * @exception IOException on errors. */ @Override public void encode(OutputStream out) throws IOException { // Nothing for default if (version == V1) { return; } try (DerOutputStream tmp = new DerOutputStream(); DerOutputStream seq = new DerOutputStream()) { tmp.putInteger(new BigInt(version)); seq.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0), tmp); out.write(seq.toByteArray()); } } /** * Decode the CertificateVersion period in DER form from the stream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on errors. */ @Override public void decode(InputStream in) throws IOException { DerValue derVal = new DerValue(in); construct(derVal); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { if (!(obj instanceof Integer)) { throw new IOException("Attribute must be of type Integer."); } if (name.equalsIgnoreCase(VERSION)) { version = ((Integer) obj).intValue(); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateVersion."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(VERSION)) { return (Integer.valueOf(getVersion())); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateVersion."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(VERSION)) { version = V1; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateVersion."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(VERSION); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } /** * Compare versions. */ public int compare(int vers) { return (version - vers); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateX509Key.java000066400000000000000000000130351412550063600303120ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.Serializable; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class defines the X509Key attribute for the Certificate. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.5 * @see CertAttrSet */ public class CertificateX509Key implements CertAttrSet, Serializable { /** * */ private static final long serialVersionUID = 6718749024328681131L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.key"; /** * Sub attributes name for this CertAttrSet. */ public static final String NAME = "key"; public static final String KEY = "value"; // Private data member private X509Key key; /** * Default constructor for the certificate attribute. * * @param key the X509Key */ public CertificateX509Key(X509Key key) { this.key = key; } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the X509Key from. * @exception IOException on decoding errors. */ public CertificateX509Key(DerInputStream in) throws IOException { DerValue val = in.getDerValue(); key = X509Key.parse(val); } /** * Create the object, decoding the values from the passed stream. * * @param in the InputStream to read the X509Key from. * @exception IOException on decoding errors. */ public CertificateX509Key(InputStream in) throws IOException { DerValue val = new DerValue(in); key = X509Key.parse(val); } /** * Return the key as printable string. */ @Override public String toString() { if (key == null) return ""; return (key.toString()); } /** * Decode the key in DER form from the stream. * * @param in the InputStream to unmarshal the contents from * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { DerValue val = new DerValue(in); key = X509Key.parse(val); } private void writeObject(ObjectOutputStream stream) throws IOException { encode(stream); } private void readObject(ObjectInputStream stream) throws IOException { decode(stream); } /** * Encode the key in DER form to the stream. * * @param out the OutputStream to marshal the contents to. * @exception IOException on errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); key.encode(tmp); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { if (!(obj instanceof X509Key)) { throw new IOException("Attribute must be of type X509Key."); } if (name.equalsIgnoreCase(KEY)) { this.key = (X509Key) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateX509Key."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(KEY)) { return (key); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateX509Key."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(KEY)) { key = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: CertificateX509Key."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(KEY); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/ChallengePassword.java000066400000000000000000000077761412550063600304550ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerValue; /** * Class for handling the decoding of a SCEP Challenge Password * object. Currently this class cannot be used for encoding * thus some fo the methods are unimplemented */ public class ChallengePassword implements CertAttrSet { public static final String NAME = "ChallengePassword"; public static final String PASSWORD = "password"; private String cpw; /** * Get the password marshalled in this object * * @return the challenge password */ @Override public String toString() { return cpw; } /** * Create a ChallengePassword object * * @param stuff (must be of type byte[]) a DER-encoded by array following * The ASN.1 template for ChallenegePassword specified in the SCEP * documentation * @throws IOException if the DER encoded byt array was malformed, or if it * did not match the template */ public ChallengePassword(Object stuff) throws IOException { ByteArrayInputStream is = new ByteArrayInputStream((byte[]) stuff); try { decode(is); } catch (Exception e) { throw new IOException(e.getMessage()); } } /** * Currently Unimplemented */ @Override public void encode(OutputStream out) throws CertificateException, IOException { } @Override public void decode(InputStream in) throws CertificateException, IOException { DerValue derVal = new DerValue(in); construct(derVal); } private void construct(DerValue derVal) throws IOException { try { cpw = derVal.getDirectoryString(); } catch (NullPointerException e) { cpw = ""; } } /** * Currently Unimplemented */ @Override public void set(String name, Object obj) throws CertificateException, IOException { } /** * Get an attribute of this object. * * @param name the name of the attribute of this object to get. The only * supported attribute is "password" */ @Override public Object get(String name) throws CertificateException, IOException { if (name.equalsIgnoreCase(PASSWORD)) { return cpw; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet: ChallengePassword"); } } /** * Currently Unimplemented */ @Override public void delete(String name) throws CertificateException, IOException { } /** * @return an empty set of elements */ @Override public Enumeration getAttributeNames() { return (new Vector()).elements(); } /** * @return the String "ChallengePassword" */ @Override public String getName() { return NAME; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/DNSName.java000066400000000000000000000047251412550063600262640ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class implements the DNSName as required by the GeneralNames * ASN.1 object. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.4 */ public class DNSName implements GeneralNameInterface { /** * */ private static final long serialVersionUID = -2907649488092607056L; private String name; /** * Create the DNSName object from the passed encoded Der value. * * @param derValue the encoded DER DNSName. * @exception IOException on error. */ public DNSName(DerValue derValue) throws IOException { name = derValue.getIA5String(); } /** * Create the DNSName object with the specified name. * * @param name the DNSName. */ public DNSName(String name) { this.name = name; } /** * Return the type of the GeneralName. */ @Override public int getType() { return (GeneralNameInterface.NAME_DNS); } /** * Encode the DNS name into the DerOutputStream. * * @param out the DER stream to encode the DNSName to. * @exception IOException on encoding errors. */ @Override public void encode(DerOutputStream out) throws IOException { out.putIA5String(name); } /** * Convert the name into user readable string. */ @Override public String toString() { return ("DNSName: " + name); } /** * Get the raw DNSName value. */ public String getValue() { return name; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/DeltaCRLIndicatorExtension.java000066400000000000000000000177161412550063600321670ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.math.BigInteger; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * Represent the Delta CRL Indicator Extension. * *

* The delta CRL indicator is a critical CRL extension that identifies a delta-CRL. The value of BaseCRLNumber * identifies the CRL number of the base CRL that was used as the starting point in the generation of this delta- CRL. * The delta-CRL contains the changes between the base CRL and the current CRL issued along with the delta-CRL. * * @see Extension * @see CertAttrSet */ public class DeltaCRLIndicatorExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 7182919216525364676L; /** * Attribute name. */ public static final String NAME = "DeltaCRLIndicator"; public static final String NUMBER = "value"; /** * The Object Identifier for this extension. */ public static final String OID = "2.5.29.27"; private BigInt baseCRLNumber = null; static { try { OIDMap.addAttribute(DeltaCRLIndicatorExtension.class.getName(), OID, NAME); } catch (CertificateException e) { } } // Encode this extension value private void encodeThis() throws IOException { if (baseCRLNumber == null) throw new IOException("Unintialized delta CRL indicator extension"); try (DerOutputStream os = new DerOutputStream()) { os.putInteger(this.baseCRLNumber); this.extensionValue = os.toByteArray(); } } /** * Create a DeltaCRLIndicatorExtension with the integer value. * The criticality is set to true. * * @param baseCRLNum the value to be set for the extension. */ public DeltaCRLIndicatorExtension(int baseCRLNum) throws IOException { this.baseCRLNumber = new BigInt(baseCRLNum); this.extensionId = PKIXExtensions.DeltaCRLIndicator_Id; this.critical = true; encodeThis(); } /** * Create a DeltaCRLIndicatorExtension with the BigInteger value. * The criticality is set to true. * * @param baseCRLNum the value to be set for the extension. */ public DeltaCRLIndicatorExtension(BigInteger baseCRLNum) throws IOException { this.baseCRLNumber = new BigInt(baseCRLNum); this.extensionId = PKIXExtensions.DeltaCRLIndicator_Id; this.critical = true; encodeThis(); } /** * Create a DeltaCRLIndicatorExtension with the BigInteger value. * * @param critical true if the extension is to be treated as critical. * @param baseCRLNum the value to be set for the extension. */ public DeltaCRLIndicatorExtension(Boolean critical, BigInteger baseCRLNum) throws IOException { this.baseCRLNumber = new BigInt(baseCRLNum); this.extensionId = PKIXExtensions.DeltaCRLIndicator_Id; this.critical = critical.booleanValue(); encodeThis(); } /** * Create the extension from the passed DER encoded value of the same. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public DeltaCRLIndicatorExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.DeltaCRLIndicator_Id; this.critical = critical.booleanValue(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); this.baseCRLNumber = val.getInteger(); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { if (name.equalsIgnoreCase(NUMBER)) { if (!(obj instanceof BigInteger)) { throw new IOException("Attribute must be of type BigInteger."); } baseCRLNumber = new BigInt((BigInteger) obj); } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:DeltaCRLIndicator."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(NUMBER)) { if (baseCRLNumber == null) return null; else return baseCRLNumber.toBigInteger(); } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:DeltaCRLIndicator."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(NUMBER)) { baseCRLNumber = null; } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:DeltaCRLIndicator."); } } /** * Returns a printable representation of the DeltaCRLIndicatorExtension. */ @Override public String toString() { String s = super.toString() + "Delta CRL Indicator: " + ((baseCRLNumber == null) ? "" : baseCRLNumber.toString()) + "\n"; return (s); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { this.extensionId = PKIXExtensions.DeltaCRLIndicator_Id; this.critical = true; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(NUMBER); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/DirStrConverter.java000066400000000000000000000143621412550063600301340ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.CharsetEncoder; import org.mozilla.jss.netscape.security.util.ASN1CharStrConvMap; import org.mozilla.jss.netscape.security.util.DerValue; /** * A DirStrConverter converts a string to a DerValue of ASN.1 Directory String, * which is a CHOICE of Printable (subset of ASCII), T.61 (Teletex) or * Universal String (UCS-4), and vice versa. * *

* The string to DerValue conversion is done as follows. If the string has only PrintableString characters it is * converted to a ASN.1 Printable String using the PrintableString encoder from the global default ASN1CharStrConvMap. * If it has only characters covered in the PrintableString or T.61 character set it is converted to a ASN.1 T.61 string * using the T.61 encoder from the ASN1CharStrCovnMap. Otherwise it is converted to a ASN.1 UniversalString (UCS-4 * character set) which covers all characters. * * @see AVAValueConverter * @see ASN1CharStrConvMap * * @author Lily Hsiao, Slava Galperin at Netscape Communications, Inc. */ public class DirStrConverter implements AVAValueConverter { // public constructors /** * Constructs a DirStrConverter. */ public DirStrConverter() { } // public functions /** * Converts a string to a DER encoded ASN1 Directory String, which is a * CHOICE of PrintableString, T.61String or UniversalString. * The string is taken as is i.e. should not be in Ldap DN string syntax. * * @param ds a string representing a directory string value. * * @return a DerValue * * @exception IOException if the string cannot be converted, such as * when a UniversalString encoder * isn't available and the string contains * characters covered only in the universal * string (or UCS-4) character set. */ private static byte[] DefEncodingOrder = new byte[] { DerValue.tag_UTF8String, DerValue.tag_PrintableString, DerValue.tag_T61String, DerValue.tag_UniversalString }; public static synchronized void setDefEncodingOrder(byte[] defEncodingOrder) { DefEncodingOrder = defEncodingOrder; } @Override public DerValue getValue(String ds) throws IOException { return getValue(ds, DefEncodingOrder); } /** * Like getValue(String) with specified DER tags as encoding order. */ @Override public DerValue getValue(String valueString, byte[] tags) throws IOException { // try to convert to printable, then t61 the universal - // i.e. from minimal to the most liberal. if (tags == null || tags.length == 0) tags = DefEncodingOrder; for (int i = 0; i < tags.length; i++) { try { CharsetEncoder encoder = ASN1CharStrConvMap.getDefault().getEncoder(tags[i]); if (encoder == null) continue; CharBuffer charBuffer = CharBuffer.wrap(valueString.toCharArray()); ByteBuffer byteBuffer = encoder.encode(charBuffer); return new DerValue(tags[i], byteBuffer.array(), byteBuffer.arrayOffset(), byteBuffer.limit()); } catch (CharacterCodingException e) { continue; } } throw new IOException( "Cannot convert the directory string value to a ASN.1 type"); } /** * Creates a DerValue from a BER encoded value, obtained from for example * a attribute value in octothorpe form of a Ldap DN string. * Checks if the BER encoded value is legal for a DirectoryString. * * NOTE: currently only supports DER encoding for the BER encoded value. * * @param berByteStream Byte array of a BER encoded value. * * @return DerValue object. * * @exception IOException If the BER value cannot be converted to a * valid Directory String DER value. */ @Override public DerValue getValue(byte[] berByteStream) throws IOException { DerValue value = new DerValue(berByteStream); /* if (value.tag != DerValue.tag_PrintableString && value.tag != DerValue.tag_T61String && value.tag != DerValue.tag_UniversalString) throw new IOException("Invalid Directory String AVA Value"); */ return value; } /** * Converts a DerValue to a string. * The string is not in any syntax, such as RFC1779 string syntax. * * @param avaValue a DerValue * @return a string if the value can be converted. * @exception IOException if a decoder needed for the * conversion is not available. */ @Override public String getAsString(DerValue avaValue) throws IOException { /* if (avaValue.tag != DerValue.tag_PrintableString && avaValue.tag != DerValue.tag_BMPString && avaValue.tag != DerValue.tag_UniversalString && avaValue.tag != DerValue.tag_T61String) throw new IllegalArgumentException( "Invalid Directory String value"); // NOTE will return null if a decoder is not available. */ return avaValue.getASN1CharString(); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/DisplayText.java000066400000000000000000000050661412550063600273100ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.Serializable; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * Represent the DisplayText. * * DisplayText ::= CHOICE { * visibleString VisibleString (SIZE (1..200)), * bmpString BMPString (SIZE (1..200)), * utf8String UTF8String (SIZE (1..200)), * } * * @author Thomas Kwan */ public class DisplayText implements Serializable { private static final long serialVersionUID = -6521458152495173328L; /** Tag value indicating an ASN.1 "BMPString" value. */ public final static byte tag_IA5String = 0x16; public final static byte tag_BMPString = 0x1E; public final static byte tag_VisibleString = 0x1A; public final static byte tag_UTF8String = 0x0C; private byte mTag; private String mS = null; public DisplayText(byte tag, String s) { mTag = tag; mS = s; } public DisplayText(DerValue val) throws IOException { mTag = val.tag; mS = val.getAsString(); } /** * Write the DisplayText to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException on errors. */ public void encode(DerOutputStream out) throws IOException { out.putStringType(mTag, mS); } public String getText() { return mS; } @Override public String toString() { if (mTag == tag_IA5String) { return "IA5String: " + mS; } else if (mTag == tag_BMPString) { return "BMPString: " + mS; } else if (mTag == tag_VisibleString) { return "VisibleString: " + mS; } else { return "UTF8String: " + mS; } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/EDIPartyName.java000066400000000000000000000122531412550063600272540ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class defines the EDIPartyName of the GeneralName choice. * The ASN.1 syntax for this is: * *

 * EDIPartyName ::= SEQUENCE {
 *     nameAssigner  [0]  DirectoryString OPTIONAL,
 *     partyName     [1]  DirectoryString }
 * 
* * @author Hemma Prafullchandra * @version 1.2 * @see GeneralName * @see GeneralNames * @see GeneralNameInterface */ public class EDIPartyName implements GeneralNameInterface { /** * */ private static final long serialVersionUID = -8669257424766789063L; // Private data members private static final byte TAG_ASSIGNER = 0; private static final byte TAG_PARTYNAME = 1; private String assigner = null; private String party = null; /** * Create the EDIPartyName object from the specified names. * * @param assignerName the name of the assigner * @param partyName the name of the EDI party. */ public EDIPartyName(String assignerName, String partyName) { this.assigner = assignerName; this.party = partyName; } /** * Create the EDIPartyName object from the specified name. * * @param partyName the name of the EDI party. */ public EDIPartyName(String partyName) { this.party = partyName; } /** * Create the EDIPartyName object from the passed encoded Der value. * * @param derValue the encoded DER EDIPartyName. * @exception IOException on error. */ public EDIPartyName(DerValue derValue) throws IOException { DerInputStream in = new DerInputStream(derValue.toByteArray()); DerValue[] seq = in.getSequence(2); int len = seq.length; if (len < 1 || len > 2) throw new IOException("Invalid encoding of EDIPartyName"); for (int i = 0; i < len; i++) { DerValue opt = seq[i]; if (opt.isContextSpecific(TAG_ASSIGNER) && !opt.isConstructed()) { if (assigner != null) throw new IOException("Duplicate nameAssigner found in" + " EDIPartyName"); opt = opt.data.getDerValue(); assigner = opt.getAsString(); } if (opt.isContextSpecific(TAG_PARTYNAME) && !opt.isConstructed()) { if (party != null) throw new IOException("Duplicate partyName found in" + " EDIPartyName"); opt = opt.data.getDerValue(); party = opt.getAsString(); } } } /** * Return the type of the GeneralName. */ @Override public int getType() { return (GeneralNameInterface.NAME_EDI); } /** * Encode the EDI party name into the DerOutputStream. * * @param out the DER stream to encode the EDIPartyName to. * @exception IOException on encoding errors. */ @Override public void encode(DerOutputStream out) throws IOException { DerOutputStream tagged = new DerOutputStream(); DerOutputStream tmp = new DerOutputStream(); if (assigner != null) { DerOutputStream tmp2 = new DerOutputStream(); // XXX - shd check is chars fit into PrintableString tmp2.putPrintableString(assigner); tagged.write(DerValue.createTag(DerValue.TAG_CONTEXT, false, TAG_ASSIGNER), tmp2); } if (party == null) { tagged.close(); tmp.close(); throw new IOException("Cannot have null partyName"); } // XXX - shd check is chars fit into PrintableString tmp.putPrintableString(party); tagged.write(DerValue.createTag(DerValue.TAG_CONTEXT, false, TAG_PARTYNAME), tmp); out.write(DerValue.tag_Sequence, tagged); } /** * Return the printable string. */ @Override public String toString() { return ("EDIPartyName: " + ((assigner == null) ? "" : (" nameAssigner = " + assigner + ",")) + " partyName = " + party); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/Extension.java000066400000000000000000000140611412550063600270050ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.Serializable; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** * Represent a X509 Extension Attribute. * *

* Extensions are addiitonal attributes which can be inserted in a X509 v3 certificate. For example a * "Driving License Certificate" could have the driving license number as a extension. * *

* Extensions are represented as a sequence of the extension identifier (Object Identifier), a boolean flag stating * whether the extension is to be treated as being critical and the extension value itself (this is again a DER encoding * of the extension value). * *

 * ASN.1 definition of Extension:
 * Extension ::= SEQUENCE {
 * ExtensionId	OBJECT IDENTIFIER,
 * critical	BOOLEAN DEFAULT FALSE,
 * extensionValue	OCTET STRING
 * }
 * 
* * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.9 */ public class Extension implements Serializable { private static final long serialVersionUID = -643549610716024753L; protected ObjectIdentifier extensionId = null; protected boolean critical = false; protected byte[] extensionValue = null; /** * Default constructor. Used only by sub-classes. */ public Extension() { } /** * Constructs an extension from a DER encoded array of bytes. */ public Extension(DerValue derVal) throws IOException { DerInputStream in = derVal.toDerInputStream(); // Object identifier extensionId = in.getOID(); // If the criticality flag was false, it will not have been encoded. DerValue val = in.getDerValue(); if (val.tag == DerValue.tag_Boolean) { critical = val.getBoolean(); // Extension value (DER encoded) val = in.getDerValue(); extensionValue = val.getOctetString(); } else { critical = false; extensionValue = val.getOctetString(); } } /** * Constructs an Extension from individual components of ObjectIdentifier, * criticality and the DER encoded OctetString. * * @param extensionId the ObjectIdentifier of the extension * @param critical the boolean indicating if the extension is critical * @param extensionValue the DER encoded octet string of the value. */ public Extension(ObjectIdentifier extensionId, boolean critical, byte[] extensionValue) throws IOException { this.extensionId = extensionId; this.critical = critical; // passed in a DER encoded octet string, strip off the tag // and length DerValue inDerVal = new DerValue(extensionValue); this.extensionValue = inDerVal.getOctetString(); } /** * Constructs an Extension from another extension. To be used for * creating decoded subclasses. * * @param ext the extension to create from. */ public Extension(Extension ext) { this.extensionId = ext.extensionId; this.critical = ext.critical; this.extensionValue = ext.extensionValue; } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors */ public void encode(DerOutputStream out) throws IOException { if (extensionId == null) throw new IOException("Null OID to encode for the extension!"); DerOutputStream bytes = new DerOutputStream(); bytes.putOID(extensionId); if (critical) bytes.putBoolean(critical); if (extensionValue != null) bytes.putOctetString(extensionValue); out.write(DerValue.tag_Sequence, bytes); } /** * Returns true if extension is critical. */ public boolean isCritical() { return (critical); } public void setCritical(boolean c) { critical = c; } public void clearValue() { extensionValue = null; } /** * Returns the ObjectIdentifier of the extension. */ public ObjectIdentifier getExtensionId() { return (extensionId); } public void setExtensionId(ObjectIdentifier oid) { extensionId = oid; } /** * Returns the extension value as an byte array for further processing. * Note, this is the raw DER value of the extension, not the DER * encoded octet string which is in the certificate. */ public byte[] getExtensionValue() { if (extensionValue == null) return null; byte[] dup = new byte[extensionValue.length]; System.arraycopy(extensionValue, 0, dup, 0, dup.length); return dup; } public void setExtensionValue(byte value[]) { extensionValue = value; } /** * Returns the Extension in user readable form. */ @Override public String toString() { String s = "ObjectId: " + extensionId.toString(); if (critical) { s += " Criticality=true\n"; } else { s += " Criticality=false\n"; } return (s); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/Extensions.java000066400000000000000000000202321412550063600271650ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class defines the Extensions attribute for the Certificate. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.11 * @see CertAttrSet */ public class Extensions extends Vector implements CertAttrSet { /** * */ private static final long serialVersionUID = 4597917347772057433L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions"; /** * name */ public static final String NAME = "extensions"; private Hashtable map; // Parse the encoded extension public void parseExtension(Extension ext) throws IOException { try { @SuppressWarnings("unchecked") Class extClass = (Class) OIDMap.getClass(ext.getExtensionId()); if (extClass == null) { // Unsupported extension if (ext.isCritical()) { throw new IOException("Unsupported CRITICAL extension: " + ext.getExtensionId()); } else { map.put(ext.getExtensionId().toString(), ext); addElement(ext); return; } } Class[] params = { Boolean.class, Object.class }; Constructor cons = extClass.getConstructor(params); byte[] extData = ext.getExtensionValue(); int extLen = extData.length; Object value = Array.newInstance(byte.class, extLen); for (int i = 0; i < extLen; i++) { Array.setByte(value, i, extData[i]); } Object[] passed = new Object[] { Boolean.valueOf(ext.isCritical()), value }; CertAttrSet certExt = cons.newInstance(passed); map.put(certExt.getName(), (Extension) certExt); addElement((Extension) certExt); } catch (NoSuchMethodException nosuch) { throw new IOException(nosuch.toString()); } catch (InvocationTargetException invk) { throw new IOException(invk.getTargetException().toString()); } catch (Exception e) { throw new IOException(e.toString()); } } /** * Default constructor for the certificate attribute. */ public Extensions() { map = new Hashtable(); } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the Extension from. * @exception IOException on decoding errors. */ public Extensions(DerInputStream in) throws IOException { map = new Hashtable(); DerValue[] exts = in.getSequence(5); for (int i = 0; i < exts.length; i++) { Extension ext = new Extension(exts[i]); parseExtension(ext); } } /** * Decode the extensions from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { DerValue val = new DerValue(in); DerInputStream str = val.toDerInputStream(); map = new Hashtable(); DerValue[] exts = str.getSequence(5); for (int i = 0; i < exts.length; i++) { Extension ext = new Extension(exts[i]); parseExtension(ext); } } /** * Encode the extensions in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @exception CertificateException on encoding errors. * @exception IOException on errors. */ @Override public void encode(OutputStream out) throws CertificateException, IOException { DerOutputStream extOut = new DerOutputStream(); for (int i = 0; i < size(); i++) { Object thisOne = elementAt(i); if (thisOne instanceof CertAttrSet) ((CertAttrSet) thisOne).encode(extOut); else if (thisOne instanceof Extension) ((Extension) thisOne).encode(extOut); else throw new CertificateException("Invalid extension object"); } try (DerOutputStream seq = new DerOutputStream()) { seq.write(DerValue.tag_Sequence, extOut); out.write(seq.toByteArray()); } } /** * Set the attribute value. * * @param name the extension name used in the cache. * @param obj the object to set. * @exception IOException if the object could not be cached. */ @Override public void set(String name, Object obj) throws IOException { map.put(name, (Extension) obj); addElement((Extension) obj); } /** * Get the attribute value. * * @param name the extension name used in the lookup. * @exception IOException if named extension is not found. */ @Override public Object get(String name) throws IOException { Object obj = map.get(name); if (obj == null) { throw new IOException("No extension found with name " + name); } return (obj); } /** * Delete the attribute value. * * @param name the extension name used in the lookup. * @exception IOException if named extension is not found. */ @Override public void delete(String name) throws IOException { Object obj = map.get(name); if (obj == null) { throw new IOException("No extension found with name " + name); } map.remove(name); removeElement(obj); } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { return map.keys(); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + ((map == null) ? 0 : map.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (!super.equals(obj)) return false; if (getClass() != obj.getClass()) return false; Extensions other = (Extensions) obj; if (map == null) { if (other.map != null) return false; } else if (!map.equals(other.map)) return false; return true; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/ExtensionsRequested.java000066400000000000000000000122461412550063600310550ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerValue; public class ExtensionsRequested implements CertAttrSet { public static final String NAME = "EXTENSIONS_REQUESTED"; public static final String KUE_DIGITAL_SIGNATURE = "kue_digital_signature"; public static final String KUE_KEY_ENCIPHERMENT = "kue_key_encipherment"; private String kue_digital_signature = "false"; private String kue_key_encipherment = "false"; private Vector exts = new Vector(); public ExtensionsRequested(Object stuff) throws IOException { ByteArrayInputStream is = new ByteArrayInputStream((byte[]) stuff); try { decode(is); } catch (Exception e) { e.printStackTrace(); throw new IOException(e.getMessage()); } } @Override public void encode(OutputStream out) throws CertificateException, IOException { } @Override public void decode(InputStream in) throws CertificateException, IOException { DerValue derVal = new DerValue(in); construct(derVal); } @Override public void set(String name, Object obj) throws CertificateException, IOException { } @Override public Object get(String name) throws CertificateException, IOException { if (name.equalsIgnoreCase(KUE_DIGITAL_SIGNATURE)) { return kue_digital_signature; } if (name.equalsIgnoreCase(KUE_KEY_ENCIPHERMENT)) { return kue_key_encipherment; } throw new IOException("Unsupported attribute queried"); } @Override public void delete(String name) throws CertificateException, IOException { } @Override public Enumeration getAttributeNames() { return (new Vector()).elements(); } @Override public String getName() { return NAME; } /** * construct - expects this in the inputstream (from the router): * * 211 30 31: SEQUENCE { * 213 06 10: OBJECT IDENTIFIER '2 16 840 1 113733 1 9 8' * 225 31 17: SET { * 227 04 15: OCTET STRING, encapsulates { * 229 30 13: SEQUENCE { * 231 30 11: SEQUENCE { * 233 06 3: OBJECT IDENTIFIER keyUsage (2 5 29 15) * 238 04 4: OCTET STRING * : 03 02 05 A0 * : } * : } * : } * * or this (from IRE client): * * 262 30 51: SEQUENCE { * 264 06 9: OBJECT IDENTIFIER extensionReq (1 2 840 113549 1 9 14) * 275 31 38: SET { * 277 30 36: SEQUENCE { * 279 30 34: SEQUENCE { * 281 06 3: OBJECT IDENTIFIER subjectAltName (2 5 29 17) * 286 04 27: OCTET STRING * : 30 19 87 04 D0 0C 3E 6F 81 03 61 61 61 82 0C 61 * : 61 61 2E 6D 63 6F 6D 2E 63 6F 6D * : } * : } * : } * : } */ private void construct(DerValue dv) throws IOException { DerInputStream stream = null; try { // try decoding as sequence first stream = dv.toDerInputStream(); stream.getDerValue(); // consume stream stream.reset(); stream.getSequence(2); // consume stream } catch (IOException ioe) { // if it failed, the outer sequence may be // encapsulated in an octet string, as in the first // example above byte[] octet_string = dv.getOctetString(); // Make a new input stream from the byte array, // and re-parse it as a sequence. dv = new DerValue(octet_string); stream = dv.toDerInputStream(); stream.getSequence(2); // consume stream } // now, the stream will be in the correct format stream.reset(); while (true) { DerValue ext_dv = null; try { ext_dv = stream.getDerValue(); } catch (IOException ex) { break; } Extension ext = new Extension(ext_dv); exts.addElement(ext); } } public Vector getExtensions() { return exts; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/FreshestCRLExtension.java000066400000000000000000000323721412550063600310570ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.netscape.security.util.BitArray; import org.mozilla.jss.netscape.security.util.DerOutputStream; /** * An extension that tells applications where to find * the latest (freshest) delta CRL for this certificate * or full CRL. * *
 * cRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
 *
 * DistributionPoint ::= SEQUENCE {
 *      distributionPoint       [0]     DistributionPointName OPTIONAL,
 *      reasons                 [1]     ReasonFlags OPTIONAL,
 *      cRLIssuer               [2]     GeneralNames OPTIONAL }
 *
 * DistributionPointName ::= CHOICE {
 *      fullName                [0]     GeneralNames,
 *      nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
 *
 * ReasonFlags ::= BIT STRING {
 *      unused                  (0),
 *      keyCompromise           (1),
 *      cACompromise            (2),
 *      affiliationChanged      (3),
 *      superseded              (4),
 *      cessationOfOperation    (5),
 *      certificateHold         (6) }
 * 
*/ public class FreshestCRLExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -8040203589629281781L; // vector of CRLDistributionPoint private SEQUENCE distributionPoints = new SEQUENCE(); public FreshestCRLExtension() { this.extensionId = PKIXExtensions.FreshestCRL_Id; this.critical = false; } // Cached DER-encoding to improve performance. private byte[] cachedEncoding = null; // Attribute name public static final String NAME = "FreshestCRL"; // The Object Identifier for this extension. public static final String OID = "2.5.29.46"; static { try { OIDMap.addAttribute(FreshestCRLExtension.class.getName(), OID, NAME); } catch (CertificateException e) { } } /** * This constructor is called by the CertificateExtensions class to decode * an extension whose OID indicates it is a CRLDistributionsPoints * extension. */ public FreshestCRLExtension(Boolean critical, Object value) //throws IOException { try { this.extensionId = PKIXExtensions.FreshestCRL_Id; this.critical = critical.booleanValue(); this.extensionValue = ((byte[]) value).clone(); // decode the value try { SEQUENCE.OF_Template seqOfCRLDP = new SEQUENCE.OF_Template(CRLDistributionPoint.getTemplate()); distributionPoints = (SEQUENCE) ASN1Util.decode(seqOfCRLDP, extensionValue); } catch (InvalidBERException e) { throw new IOException("Invalid BER-encoding: " + e, e); } } catch (IOException e) { System.out.println("Big error"); System.out.println(e); e.printStackTrace(); //throw e; } } /** * Creates a new FreshestCRL extension, with the given * distribution point as the first element. */ public FreshestCRLExtension(CRLDistributionPoint dp) { this.extensionId = PKIXExtensions.FreshestCRL_Id; this.critical = false; distributionPoints.addElement(dp); } /** * Adds an additional distribution point to the end of the sequence. */ public void addPoint(CRLDistributionPoint dp) { distributionPoints.addElement(dp); cachedEncoding = null; } /** * Returns the number of distribution points in the sequence. */ public int getNumPoints() { return distributionPoints.size(); } /** * Returns the DistributionPoint at the given index in the sequence. */ public CRLDistributionPoint getPointAt(int index) { return (CRLDistributionPoint) distributionPoints.elementAt(index); } /** * Sets the criticality of this extension. PKIX dictates that this * extension SHOULD NOT be critical, so applications can make it critical * if they have a very good reason. By default, the extension is not * critical. */ @Override public void setCritical(boolean critical) { this.critical = critical; } /** * Encodes this extension to the given DerOutputStream. * This method re-encodes each time it is called, so it is not very * efficient. */ @Override public void encode(DerOutputStream out) throws IOException { extensionValue = ASN1Util.encode(distributionPoints); super.encode(out); } /** * Should be called if any change is made to this data structure * so that the cached DER encoding can be discarded. */ public void flushCachedEncoding() { cachedEncoding = null; } ///////////////////////////////////////////////////////////// // CertAttrSet interface // This interface is not really appropriate for this extension // because it is so complicated. Therefore, we only provide a // minimal implementation. ///////////////////////////////////////////////////////////// @Override public String toString() { return NAME; } /** * DER-encodes this extension to the given OutputStream. */ @Override public void encode(OutputStream ostream) throws CertificateException, IOException { if (cachedEncoding == null) { // only re-encode if necessary DerOutputStream tmp = new DerOutputStream(); encode(tmp); cachedEncoding = tmp.toByteArray(); } ostream.write(cachedEncoding); } @Override public void decode(InputStream in) throws CertificateException, IOException { throw new IOException("Not supported"); } @Override public void set(String name, Object obj) throws CertificateException, IOException { throw new IOException("Attribute name not recognized by " + "CertAttrSet:FreshestCRLExtension"); } @Override public Object get(String name) throws CertificateException, IOException { throw new IOException("Attribute name not recognized by " + "CertAttrSet:FreshestCRLExtension"); } @Override public void delete(String name) throws CertificateException, IOException { throw new IOException("Attribute name not recognized by " + "CertAttrSet:FreshestCRLExtension"); } /* * TODO replacewith empty collection */ @Override public Enumeration getAttributeNames() { return (new Vector()).elements(); } @Override public String getName() { return NAME; } /** * Test driver. */ public static void main(String args[]) { BufferedOutputStream bos = null; try { if (args.length != 1) { System.out.println("Usage: FreshestCRLExtentions " + ""); System.exit(-1); } bos = new BufferedOutputStream( new FileOutputStream(args[0])); // URI only CRLDistributionPoint cdp = new CRLDistributionPoint(); URIName uri = new URIName("http://www.mycrl.com/go/here"); GeneralNames generalNames = new GeneralNames(); generalNames.addElement(uri); cdp.setFullName(generalNames); FreshestCRLExtension crldpExt = new FreshestCRLExtension(cdp); // DN only cdp = new CRLDistributionPoint(); X500Name dn = new X500Name("CN=Otis Smith,E=otis@fedoraproject.org" + ",OU=Certificate Server,O=Fedora,C=US"); generalNames = new GeneralNames(); generalNames.addElement(dn); cdp.setFullName(generalNames); crldpExt.addPoint(cdp); // DN + reason BitArray ba = new BitArray(5, new byte[] { (byte) 0x28 }); cdp = new CRLDistributionPoint(); cdp.setFullName(generalNames); cdp.setReasons(ba); crldpExt.addPoint(cdp); // relative DN + reason + crlIssuer cdp = new CRLDistributionPoint(); RDN rdn = new RDN("OU=foobar dept"); cdp.setRelativeName(rdn); cdp.setReasons(ba); cdp.setCRLIssuer(generalNames); crldpExt.addPoint(cdp); crldpExt.setCritical(true); crldpExt.encode(bos); } catch (Exception e) { e.printStackTrace(); } finally { if (bos != null) { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * Represents a reason that a cert may be revoked. These reasons are * expressed in a ReasonFlags bit string. */ public static class Reason { private String name; private byte bitMask; private Reason() { } private Reason(String name, byte bitMask) { this.name = name; this.bitMask = bitMask; map.put(name, this); list.addElement(this); } private static Hashtable map = new Hashtable(); private static Vector list = new Vector(); public static Reason fromString(String name) { return map.get(name); } public String getName() { return name; } public byte getBitMask() { return bitMask; } /** * Given a bit array representing reason flags, extracts the reasons * and returns them as an array. * * @param bitFlags A bit vector containing reason flags. * @return An array of reasons contained in the bit vector. * May be zero-length but will not be null. */ public static Reason[] bitArrayToReasonArray(byte bitFlags) { return bitArrayToReasonArray(new byte[] { bitFlags }); } /** * Given a bit array representing reason flags, extracts the reasons * and returns them as an array. Currently, only the first byte * of the bitflags are examined. * * @param bitFlags A bit vector containing reason flags. The format * is big-endian (MSB first). Only the first byte is examined. * @return An array of reasons contained in the bit vector. * May be zero-length but will not be null. */ public static Reason[] bitArrayToReasonArray(byte[] bitFlags) { byte first = bitFlags[0]; int size = list.size(); Vector result = new Vector(); for (int i = 0; i < size; i++) { Reason r = list.elementAt(i); byte b = r.getBitMask(); if ((first & b) != 0) { result.addElement(r); } } size = result.size(); Reason[] retval = new Reason[size]; for (int i = 0; i < size; i++) { retval[i] = result.elementAt(i); } return retval; } public static final Reason UNUSED = new Reason("unused", (byte) 0x80); public static final Reason KEY_COMPROMISE = new Reason("keyCompromise", (byte) 0x40); public static final Reason CA_COMPROMISE = new Reason("cACompromise", (byte) 0x20); public static final Reason AFFILIATION_CHANGED = new Reason("affiliationChanged", (byte) 0x10); public static final Reason SUPERSEDED = new Reason("superseded", (byte) 0x08); public static final Reason CESSATION_OF_OPERATION = new Reason("cessationOfOperation", (byte) 0x04); public static final Reason CERTIFICATE_HOLD = new Reason("certificateHold", (byte) 0x02); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/GeneralName.java000066400000000000000000000177021412550063600272140ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class implements the ASN.1 GeneralName object class. *

* The ASN.1 syntax for this is: * *

 * GeneralName ::= CHOICE {
 *    otherName                       [0]     OtherName,
 *    rfc822Name                      [1]     IA5String,
 *    dNSName                         [2]     IA5String,
 *    x400Address                     [3]     ORAddress,
 *    directoryName                   [4]     Name,
 *    ediPartyName                    [5]     EDIPartyName,
 *    uniformResourceIdentifier       [6]     IA5String,
 *    iPAddress                       [7]     OCTET STRING,
 *    registeredID                    [8]     OBJECT IDENTIFIER
 * }
 * 
* * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.7 */ public class GeneralName implements GeneralNameInterface { /** * */ private static final long serialVersionUID = 2244101501095555042L; // Private data members private GeneralNameInterface name = null; /** * Default constructor for the class. * * @param name the selected CHOICE from the list. */ public GeneralName(GeneralNameInterface name) { this.name = name; } /** * Create the object from its DER encoded value. * * @param encName the DER encoded GeneralName. */ public GeneralName(DerValue encName) throws IOException { short tag = (byte) (encName.tag & 0x1f); // NB. this is always encoded with the IMPLICIT tag // The checks only make sense if we assume implicit tagging, // with explicit tagging the form is always constructed. switch (tag) { case GeneralNameInterface.NAME_RFC822: if (encName.isContextSpecific() && !encName.isConstructed()) { encName.resetTag(DerValue.tag_IA5String); name = new RFC822Name(encName); } else throw new IOException("Invalid encoding of RFC822 name"); break; case GeneralNameInterface.NAME_DNS: if (encName.isContextSpecific() && !encName.isConstructed()) { encName.resetTag(DerValue.tag_IA5String); name = new DNSName(encName); } else throw new IOException("Invalid encoding of DNS name"); break; case GeneralNameInterface.NAME_URI: if (encName.isContextSpecific() && !encName.isConstructed()) { encName.resetTag(DerValue.tag_IA5String); name = new URIName(encName); } else throw new IOException("Invalid encoding of URI"); break; case GeneralNameInterface.NAME_IP: if (encName.isContextSpecific() && !encName.isConstructed()) { encName.resetTag(DerValue.tag_OctetString); name = new IPAddressName(encName); } else throw new IOException("Invalid encoding of IP address"); break; case GeneralNameInterface.NAME_ANY: if (encName.isContextSpecific() && encName.isConstructed()) { encName.resetTag(DerValue.tag_OctetString); name = new OtherName(encName); } else throw new IOException("Invalid encoding of other name"); break; case GeneralNameInterface.NAME_OID: if (encName.isContextSpecific() && !encName.isConstructed()) { encName.resetTag(DerValue.tag_ObjectId); name = new OIDName(encName); } else throw new IOException("Invalid encoding of OID name"); break; case GeneralNameInterface.NAME_DIRECTORY: if (encName.isContextSpecific() && encName.isConstructed()) { // Unlike the other cases, DirectoryName is EXPLICITly // tagged, because the X.500 Name type is a CHOICE. // Therefore, the sequence is actually nested in the // content of this value. We'll pretend it's an octet // string so we can get at the content bytes. encName.resetTag(DerValue.tag_OctetString); byte[] content = encName.getOctetString(); name = new X500Name(content); } else throw new IOException("Invalid encoding of Directory name"); break; case GeneralNameInterface.NAME_EDI: if (encName.isContextSpecific() && encName.isConstructed()) { encName.resetTag(DerValue.tag_Sequence); name = new EDIPartyName(encName); } else throw new IOException("Invalid encoding of EDI name"); break; default: throw new IOException("Unrecognized GeneralName tag, (" + tag + ")"); } } /** * Return the type of the general name. */ @Override public int getType() { return (name.getType()); } /** * Return the name as user readable string */ @Override public String toString() { return (name.toString()); } /** * Encode the name to the specified DerOutputStream. * * @param out the DerOutputStream to encode the the GeneralName to. * @exception IOException on encoding errors. */ @Override public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); name.encode(tmp); int nameType = name.getType(); boolean constructedForm; if (nameType == GeneralNameInterface.NAME_ANY || nameType == GeneralNameInterface.NAME_X400 || nameType == GeneralNameInterface.NAME_DIRECTORY || nameType == GeneralNameInterface.NAME_EDI) { constructedForm = true; } else { constructedForm = false; } if (nameType == GeneralNameInterface.NAME_DIRECTORY) { // EXPLICIT tag, because Name is a CHOICE type out.write(DerValue.createTag(DerValue.TAG_CONTEXT, constructedForm, (byte) nameType), tmp); } else { // IMPLICIT tag, the default out.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, constructedForm, (byte) nameType), tmp); } } @Override public boolean validSingle() { if (this == name) return false; // can't happen, but just in case... return name.validSingle(); } @Override public boolean validSubtree() { if (this == name) return false; // can't happen, but just in case... return name.validSubtree(); } /** * Unwrap this GeneralName until we reach something that is not * a GeneralName. */ public GeneralNameInterface unwrap() { if (this == name) return null; // can't happen, but just in case... if (name instanceof GeneralName) return ((GeneralName) name).unwrap(); else return name; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/GeneralNameInterface.java000066400000000000000000000046071412550063600310350ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import org.mozilla.jss.netscape.security.util.DerOutputStream; /** * This interface specifies the abstract methods which have to be * implemented by all the members of the GeneralNames ASN.1 object. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.6 */ public interface GeneralNameInterface extends java.io.Serializable { /** * The list of names supported. */ public static final int NAME_ANY = 0; public static final int NAME_RFC822 = 1; public static final int NAME_DNS = 2; public static final int NAME_X400 = 3; public static final int NAME_DIRECTORY = 4; public static final int NAME_EDI = 5; public static final int NAME_URI = 6; public static final int NAME_IP = 7; public static final int NAME_OID = 8; /** * Return the type of the general name, as * defined above. */ int getType(); /** * Encode the name to the specified DerOutputStream. * * @param out the DerOutputStream to encode the GeneralName to. * @exception IOException thrown if the GeneralName could not be * encoded. */ void encode(DerOutputStream out) throws IOException; /** * Whether the name is valid as a single name (e.g. for use in * Subject Alternative Name extension). */ default boolean validSingle() { return true; } /** * Whether the name is valid as a subtree name (e.g. for use in * Name Constraints extension) */ default boolean validSubtree() { return true; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/GeneralNames.java000066400000000000000000000122311412550063600273670ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This object class represents the GeneralNames type required in * X509 certificates. *

* The ASN.1 syntax for this is: * *

 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
 * 
* * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.7 */ public class GeneralNames extends Vector { /** * */ private static final long serialVersionUID = 3204492869396713312L; /** * Create the GeneralNames, decoding from the passed DerValue. * * Caution when using this constructor. It may be broken! * Better to call addElement(gni) directly where gni is * a GeneralNameInterface object * * @param derVal the DerValue to construct the GeneralNames from. * @exception GeneralNamesException on decoding error. * @exception IOException on error. */ public GeneralNames(DerValue derVal) throws IOException, GeneralNamesException { if (derVal.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for GeneralNames."); } if (derVal.data.available() == 0) { throw new GeneralNamesException("No data available in " + "passed DER encoded value."); } // Decode all the GeneralName's while (derVal.data.available() != 0) { DerValue encName = derVal.data.getDerValue(); GeneralName name = new GeneralName(encName); addElement(name); } } /** * Create the GeneralNames * * @param names a non-empty array of names to put into the * generalNames */ public GeneralNames(GeneralNameInterface[] names) throws GeneralNamesException { if (names == null || names.length == 0) throw new GeneralNamesException("Cannot create empty GeneralNames"); for (int i = 0; i < names.length; i++) { addElement(names[i]); } } /** * The default constructor for this class. */ public GeneralNames() { super(1, 1); } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception GeneralNamesException on encoding error. * @exception IOException on error. */ public void encode(DerOutputStream out) throws IOException, GeneralNamesException { if (size() == 0) { return; } Enumeration names = elements(); DerOutputStream temp = new DerOutputStream(); while (names.hasMoreElements()) { Object obj = names.nextElement(); if (!(obj instanceof GeneralNameInterface)) { throw new GeneralNamesException("Element in GeneralNames " + "not of type GeneralName."); } GeneralNameInterface intf = (GeneralNameInterface) obj; if (obj instanceof GeneralName) { intf.encode(temp); } else { DerOutputStream gname = new DerOutputStream(); intf.encode(gname); int nameType = intf.getType(); // constructed form if (nameType == GeneralNameInterface.NAME_ANY || nameType == GeneralNameInterface.NAME_X400 || nameType == GeneralNameInterface.NAME_EDI) { temp.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) nameType), gname); } else if (nameType == GeneralNameInterface.NAME_DIRECTORY) { // EXPLICIT tag because directoryName is a CHOICE temp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) nameType), gname); } else // primitive form temp.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, false, (byte) nameType), gname); } } out.write(DerValue.tag_Sequence, temp); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/GeneralNamesException.java000066400000000000000000000040031412550063600312440ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.security.GeneralSecurityException; /** * Generic General Names Exception. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.4 */ public class GeneralNamesException extends GeneralSecurityException { /** * */ private static final long serialVersionUID = -8320001725384815795L; /** * Constructs a GeneralNamesException with no detail message. */ public GeneralNamesException() { super(); } /** * Constructs the exception with the specified error message. * * @param message the requisite error message. */ public GeneralNamesException(String message) { super(message); } /** * Constructs the exception with the specified error message and cause. * * @param mesg the requisite error message. * @param cause the requisite cause of this error. */ public GeneralNamesException(String mesg, Throwable cause) { super(mesg, cause); } /** * Constructs the exception with the specified cause. * * @param cause the requisite cause of this error. */ public GeneralNamesException(Throwable cause) { super(cause); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/GeneralSubtree.java000066400000000000000000000125471412550063600277470ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.Serializable; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.PrettyPrintFormat; /** * Represent the GeneralSubtree ASN.1 object, whose syntax is: * *
 * GeneralSubtree ::= SEQUENCE {
 *    base             GeneralName,
 *    minimum  [0]     BaseDistance DEFAULT 0,
 *    maximum  [1]     BaseDistance OPTIONAL
 * }
 * BaseDistance ::= INTEGER (0..MAX)
 * 
* * @version 1.5 * @author Amit Kapoor * @author Hemma Prafullchandra */ public class GeneralSubtree implements Serializable { private static final long serialVersionUID = -2835481424013062770L; private static final byte TAG_MIN = 0; private static final byte TAG_MAX = 1; private static final int MIN_DEFAULT = 0; private GeneralName name; private int minimum = MIN_DEFAULT; private int maximum = -1; private transient PrettyPrintFormat pp = new PrettyPrintFormat(":"); /** * The default constructor for the class. * * @param name the GeneralName * @param min the minimum BaseDistance * @param max the maximum BaseDistance */ public GeneralSubtree(GeneralName name, int min, int max) { this.name = name; this.minimum = min; this.maximum = max; } /** * Create the object from its DER encoded form. * * @param val the DER encoded from of the same. */ public GeneralSubtree(DerValue val) throws IOException { if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for GeneralSubtree."); } name = new GeneralName(val.data.getDerValue()); // NB. this is always encoded with the IMPLICIT tag // The checks only make sense if we assume implicit tagging, // with explicit tagging the form is always constructed. while (val.data.available() != 0) { DerValue opt = val.data.getDerValue(); if (opt.isContextSpecific(TAG_MIN) && !opt.isConstructed()) { opt.resetTag(DerValue.tag_Integer); minimum = (opt.getInteger()).toInt(); } else if (opt.isContextSpecific(TAG_MAX) && !opt.isConstructed()) { opt.resetTag(DerValue.tag_Integer); maximum = (opt.getInteger()).toInt(); } else throw new IOException("Invalid encoding of GeneralSubtree."); } } /** * Return a printable string of the GeneralSubtree. */ @Override public String toString() { String s = "\n GeneralSubtree: [\n" + " GeneralName: " + ((name == null) ? "" : name.toString()) + "\n Minimum: " + minimum; if (maximum == -1) { s += "\t Maximum: undefined"; } else s += "\t Maximum: " + maximum; s += " ]\n"; return (s); } public String toPrint(int indent) { String s = "\n" + pp.indent(indent) + "GeneralSubtree: [\n" + pp.indent(indent + 2) + "GeneralName: " + ((name == null) ? "" : name.toString()) + "\n" + pp.indent(indent + 2) + "Minimum: " + minimum; if (maximum == -1) { s += "\n" + pp.indent(indent + 2) + "Maximum: undefined"; } else s += "\n" + pp.indent(indent + 2) + "Maximum: " + maximum; s += "]\n"; return (s); } /** * Encode the GeneralSubtree. * * @param out the DerOutputStream to encode this object to. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream seq = new DerOutputStream(); name.encode(seq); if (minimum != MIN_DEFAULT) { DerOutputStream tmp = new DerOutputStream(); tmp.putInteger(new BigInt(minimum)); seq.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, false, TAG_MIN), tmp); } if (maximum != -1) { DerOutputStream tmp = new DerOutputStream(); tmp.putInteger(new BigInt(maximum)); seq.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, false, TAG_MAX), tmp); } out.write(DerValue.tag_Sequence, seq); } public GeneralName getGeneralName() { return name; } public int getMaxValue() { return maximum; } public int getMinValue() { return minimum; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/GeneralSubtrees.java000066400000000000000000000065001412550063600301220ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.Serializable; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.PrettyPrintFormat; /** * Represent the GeneralSubtrees ASN.1 object. * * @version 1.4 * * @author Amit Kapoor * @author Hemma Prafullchandra */ public class GeneralSubtrees implements Serializable { private static final long serialVersionUID = 6308776640697100848L; private Vector trees; private transient PrettyPrintFormat pp = new PrettyPrintFormat(":"); /** * The default constructor for the class. * * @param trees the sequence of GeneralSubtree. */ public GeneralSubtrees(Vector trees) { this.trees = trees; } /** * Create the object from the passed DER encoded form. * * @param val the DER encoded form of the same. */ public GeneralSubtrees(DerValue val) throws IOException { trees = new Vector(1, 1); if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding of GeneralSubtrees."); } while (val.data.available() != 0) { DerValue opt = val.data.getDerValue(); GeneralSubtree tree = new GeneralSubtree(opt); trees.addElement(tree); } } /** * Return a printable string of the GeneralSubtree. */ @Override public String toString() { String s = " GeneralSubtrees:\n" + trees.toString() + "\n"; return (s); } public String toPrint(int indent) { StringBuffer s = new StringBuffer(); GeneralSubtree element; for (Enumeration e = trees.elements(); e.hasMoreElements();) { element = e.nextElement(); s.append(pp.indent(indent + 4) + element.toPrint(indent) + "\n"); } return (s.toString()); } /** * Encode the GeneralSubtrees. * * @param out the DerOutputStrean to encode this object to. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream seq = new DerOutputStream(); for (int i = 0; i < trees.size(); i++) { trees.elementAt(i).encode(seq); } out.write(DerValue.tag_Sequence, seq); } public Vector getSubtrees() { return trees; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/GenericValueConverter.java000066400000000000000000000130211412550063600312650ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.CharsetEncoder; import org.mozilla.jss.netscape.security.util.ASN1CharStrConvMap; import org.mozilla.jss.netscape.security.util.DerValue; /** * A GenericValueConverter converts a string that is not associated with * a particular attribute to a DER encoded ASN.1 character string type. * Currently supports PrintableString, IA5String, BMPString T.61String and * Universal String. * *

* The conversion is done as follows. An encoder is obtained for the all the character sets from the global default * ASN1CharStrConvMap. The encoders are then used to convert the string to the smallest character set first -- * printableString. If the string contains characters outside of that character set, it is converted to the next * character set -- IA5String character set. If that is not enough it is converted to a BMPString, then Universal String * which contains all characters. * * @author Lily Hsiao, Slava Galperin at Netscape Communications, Inc. * */ public class GenericValueConverter implements AVAValueConverter { public GenericValueConverter() { } /** * Converts a string to a DER encoded ASN.1 primtable string, defined here * as a PrintableString, IA5String, T.61String, BMPString or * UniversalString. The string is not expected to be encoded in any form. * *

* If an encoder is not available for a character set that is needed to convert the string, the string cannot be * converted and an IOException is thrown. For example, if the string contains characters outside the * PrintableString character and only a PrintableString encoder is available then an IOException is thrown. * * @param s A string representing a generic attribute string value. * * @return The DER value of the attribute. * * @exception IOException if the string cannot be converted, such as * when an encoder needed is * unavailable. */ @Override public DerValue getValue(String s) throws IOException { return getValue(s, null); } @Override public DerValue getValue(String valueString, byte[] tags) throws IOException { // try to convert to printable, then t61 the universal - // i.e. from minimal coverage to the broadest. if (tags == null || tags.length == 0) tags = DefEncodingTags; for (int i = 0; i < tags.length; i++) { try { CharsetEncoder encoder = ASN1CharStrConvMap.getDefault().getEncoder(tags[i]); if (encoder == null) continue; CharBuffer charBuffer = CharBuffer.wrap(valueString.toCharArray()); ByteBuffer byteBuffer = encoder.encode(charBuffer); return new DerValue(tags[i], byteBuffer.array(), byteBuffer.arrayOffset(), byteBuffer.limit()); } catch (CharacterCodingException e) { continue; } } throw new IOException( "Cannot convert the string value to a ASN.1 type"); } /** * Creates a DerValue from the byte array of BER encoded value. * * NOTE: currently only supports DER encoding (a form of BER) on input . * * @param berByteStream Byte array of a BER encoded value. * * @return DerValue object. * * @exception IOException If the BER value cannot be converted to a * valid Directory String DER value. */ @Override public DerValue getValue(byte[] berByteStream) throws IOException { // accepts any tag. DerValue value = new DerValue(berByteStream); return value; } /** * Converts a DerValue of ASN1 Character string type to a java string * (the string is not encoded in any form). * * @param avaValue A DerValue * @return A string representing the attribute value. * @exception IOException if a decoder needed for the * conversion is not available or if BER value * is not one of the ASN1 character string types * here. */ @Override public String getAsString(DerValue avaValue) throws IOException { return avaValue.getASN1CharString(); } private static byte DefEncodingTags[] = { DerValue.tag_PrintableString, DerValue.tag_IA5String, DerValue.tag_BMPString, DerValue.tag_UTF8String, DerValue.tag_T61String, DerValue.tag_UniversalString }; } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/HoldInstructionExtension.java000066400000000000000000000310151412550063600320540ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** * Represent the CRL Hold Instruction Code Extension. * *

* The hold instruction code is a non-critical CRL entry extension that provides a registered instruction identifier * which indicates the action to be taken after encountering a certificate that has been placed on hold. * * @see Extension * @see CertAttrSet */ public class HoldInstructionExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -6706557233070964984L; /** * Attribute name. */ public static final String NAME = "HoldInstruction"; public static final String HOLD_INSTRUCTION = "value"; /** * The Object Identifier for this extension. */ public static final String OID = "2.5.29.23"; public static final String NONE_HOLD_INSTR_OID_STR = "1.2.840.10040.2.1"; public static final ObjectIdentifier NONE_HOLD_INSTR_OID = new ObjectIdentifier(NONE_HOLD_INSTR_OID_STR); public static final String CALL_ISSUER_HOLD_INSTR_OID_STR = "1.2.840.10040.2.2"; public static final ObjectIdentifier CALL_ISSUER_HOLD_INSTR_OID = new ObjectIdentifier(CALL_ISSUER_HOLD_INSTR_OID_STR); public static final String REJECT_HOLD_INSTR_OID_STR = "1.2.840.10040.2.3"; public static final ObjectIdentifier REJECT_HOLD_INSTR_OID = new ObjectIdentifier(REJECT_HOLD_INSTR_OID_STR); private ObjectIdentifier holdInstructionCodeOIDs[] = { NONE_HOLD_INSTR_OID, CALL_ISSUER_HOLD_INSTR_OID, REJECT_HOLD_INSTR_OID }; private ObjectIdentifier holdInstructionCodeOID = null; private String holdInstructionDescription[] = { "None", "Call Issuer", "Reject" }; static { try { OIDMap.addAttribute(HoldInstructionExtension.class.getName(), OID, NAME); } catch (CertificateException e) { } } private int getHoldInstructionCodeFromOID(ObjectIdentifier oid) { for (int i = 0; i < holdInstructionCodeOIDs.length; i++) { if (oid.equals(holdInstructionCodeOIDs[i])) return (i + 1); } return 0; } private String getHoldInstructionDescription(ObjectIdentifier oid) { String description = "Invalid"; if (oid != null) { int i = getHoldInstructionCodeFromOID(oid); if (i > 0 && i < 4) description = holdInstructionDescription[i - 1]; } return (description); } // Encode this extension value private void encodeThis() throws IOException { if (holdInstructionCodeOID == null) throw new IOException("Unintialized hold instruction extension"); try (DerOutputStream os = new DerOutputStream()) { os.putOID(holdInstructionCodeOID); this.extensionValue = os.toByteArray(); } } /** * Create a HoldInstructionExtension with the date. * The criticality is set to false. * * @param code the value to be set for the extension. */ public HoldInstructionExtension(int code) throws IOException { if (code < 1 || code > 3) throw new IOException("Invalid hold instruction code"); holdInstructionCodeOID = holdInstructionCodeOIDs[code - 1]; this.extensionId = PKIXExtensions.HoldInstructionCode_Id; this.critical = false; encodeThis(); } /** * Create a HoldInstructionExtension with the date. * The criticality is set to false. * * @param oidStr the value to be set for the extension. */ public HoldInstructionExtension(String oidStr) throws IOException { ObjectIdentifier oid = new ObjectIdentifier(oidStr); if (oid == null || getHoldInstructionCodeFromOID(oid) == 0) throw new IOException("Invalid hold instruction code"); holdInstructionCodeOID = oid; this.extensionId = PKIXExtensions.HoldInstructionCode_Id; this.critical = false; encodeThis(); } /** * Create a HoldInstructionExtension with the date. * The criticality is set to false. * * @param oid the value to be set for the extension. */ public HoldInstructionExtension(ObjectIdentifier oid) throws IOException { if (getHoldInstructionCodeFromOID(oid) == 0) throw new IOException("Invalid hold instruction code"); holdInstructionCodeOID = oid; this.extensionId = PKIXExtensions.HoldInstructionCode_Id; this.critical = false; encodeThis(); } /** * Create a HoldInstructionExtension with the date. * The criticality is set to false. * * @param critical true if the extension is to be treated as critical. * @param code the value to be set for the extension. */ public HoldInstructionExtension(Boolean critical, int code) throws IOException { if (code < 1 || code > 3) throw new IOException("Invalid hold instruction code"); holdInstructionCodeOID = holdInstructionCodeOIDs[code - 1]; this.extensionId = PKIXExtensions.HoldInstructionCode_Id; this.critical = critical.booleanValue(); encodeThis(); } /** * Create a HoldInstructionExtension with the date. * The criticality is set to false. * * @param critical true if the extension is to be treated as critical. * @param oidStr the value to be set for the extension. */ public HoldInstructionExtension(Boolean critical, String oidStr) throws IOException { ObjectIdentifier oid = new ObjectIdentifier(oidStr); if (oid == null || getHoldInstructionCodeFromOID(oid) == 0) throw new IOException("Invalid hold instruction code"); holdInstructionCodeOID = oid; this.extensionId = PKIXExtensions.HoldInstructionCode_Id; this.critical = critical.booleanValue(); encodeThis(); } /** * Create a HoldInstructionExtension with the date. * The criticality is set to false. * * @param critical true if the extension is to be treated as critical. * @param oid the value to be set for the extension. */ public HoldInstructionExtension(Boolean critical, ObjectIdentifier oid) throws IOException { if (getHoldInstructionCodeFromOID(oid) == 0) throw new IOException("Invalid hold instruction code"); holdInstructionCodeOID = oid; this.extensionId = PKIXExtensions.HoldInstructionCode_Id; this.critical = critical.booleanValue(); encodeThis(); } /** * Create the extension from the passed DER encoded value of the same. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public HoldInstructionExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.HoldInstructionCode_Id; this.critical = critical.booleanValue(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); if (val.tag == DerValue.tag_ObjectId) { DerInputStream derInputStream = new DerInputStream(val.toByteArray()); holdInstructionCodeOID = derInputStream.getOID(); if (getHoldInstructionCodeFromOID(holdInstructionCodeOID) == 0) throw new IOException("Invalid encoding for HoldInstructionExtension"); } else { throw new IOException("Invalid encoding for HoldInstructionExtension"); } } /** * Get the hold instruction code. */ public ObjectIdentifier getHoldInstructionCode() { return holdInstructionCodeOID; } public String getHoldInstructionCodeDescription() { return getHoldInstructionDescription(holdInstructionCodeOID); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { if (name.equalsIgnoreCase(HOLD_INSTRUCTION)) { if (!(obj instanceof ObjectIdentifier)) { throw new IOException("Attribute must be of type String."); } holdInstructionCodeOID = (ObjectIdentifier) obj; } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:HoldInstructionCode."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(HOLD_INSTRUCTION)) { return holdInstructionCodeOID; } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:HoldInstructionCode."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(HOLD_INSTRUCTION)) { holdInstructionCodeOID = null; } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:HoldInstructionCode."); } } /** * Returns a printable representation of the HoldInstructionExtension. */ @Override public String toString() { String s = super.toString() + "Hold Instruction Code: " + getHoldInstructionDescription(holdInstructionCodeOID) + "\n"; return (s); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { this.extensionId = PKIXExtensions.HoldInstructionCode_Id; this.critical = true; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(HOLD_INSTRUCTION); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/IA5StringConverter.java000066400000000000000000000104071412550063600304660ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.CharsetEncoder; import org.mozilla.jss.netscape.security.util.ASN1CharStrConvMap; import org.mozilla.jss.netscape.security.util.DerValue; /** * A AVAValueConverter that converts a IA5String attribute to a DerValue * and vice versa. An example an attribute that is a IA5String string is "E". * * @see AVAValueConverter * * @author Lily Hsiao, Slava Galperin at Netscape Communications, Inc. */ public class IA5StringConverter implements AVAValueConverter { // public constructors /* * Contructs a IA5String Converter. */ public IA5StringConverter() { } /* * Converts a string with ASN.1 IA5String characters to a DerValue. * * @param valueString a string with IA5String characters. * * @return a DerValue. * * @exception IOException if a IA5String encoder is not * available for the conversion. */ @Override public DerValue getValue(String valueString) throws IOException { return getValue(valueString, null); } @Override public DerValue getValue(String valueString, byte[] tags) throws IOException { try { CharsetEncoder encoder = ASN1CharStrConvMap.getDefault().getEncoder(DerValue.tag_IA5String); if (encoder == null) throw new IOException("No encoder for IA5String"); CharBuffer charBuffer = CharBuffer.wrap(valueString.toCharArray()); ByteBuffer byteBuffer = encoder.encode(charBuffer); return new DerValue(DerValue.tag_IA5String, byteBuffer.array(), byteBuffer.arrayOffset(), byteBuffer.limit()); } catch (CharacterCodingException e) { throw new IllegalArgumentException("Invalid IA5String AVA Value string"); } } /* * Converts a BER encoded value of IA5String to a DER encoded value. * Checks if the BER encoded value is a IA5String. * NOTE only DER encoding is currently supported on for the BER * encoded value. * * @param berStream a byte array of the BER encoded value. * * @return a DerValue. * * @exception IOException if the BER value cannot be converted * to a IA5String DER value. */ @Override public DerValue getValue(byte[] berStream) throws IOException { DerValue value = new DerValue(berStream); if (value.tag == DerValue.tag_IA5String) return value; if (value.tag == DerValue.tag_PrintableString) return value; throw new IOException("Invalid IA5String AVA Value."); } /* * Converts a DerValue of IA5String to a java string with IA5String * characters. * * @param avaValue a DerValue. * * @return a string with IA5String characters. * * @exception IOException if the DerValue is not a IA5String i.e. * The DerValue cannot be converted to a string * with IA5String characters. */ @Override public String getAsString(DerValue avaValue) throws IOException { if (avaValue.tag == DerValue.tag_IA5String) return avaValue.getIA5String(); if (avaValue.tag == DerValue.tag_PrintableString) return avaValue.getPrintableString(); throw new IOException("Invalid IA5String AVA Value."); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/IPAddressName.java000066400000000000000000000230351412550063600274510ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.nio.ByteBuffer; import java.util.StringTokenizer; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class implements the IPAddressName as required by the GeneralNames * ASN.1 object. * * @see GeneralName * @see GeneralNameInterface * @see GeneralNames * * @version 1.2 * * @author Amit Kapoor * @author Hemma Prafullchandra */ public class IPAddressName implements GeneralNameInterface { /** * */ private static final long serialVersionUID = -4240184399679453666L; private byte[] address; /** * Create the IPAddressName object from the passed encoded Der value. * * @param derValue the encoded DER IPAddressName. * @exception IOException on error. */ public IPAddressName(DerValue derValue) throws IOException { address = derValue.getOctetString(); } /** * Create the IPAddressName object with the specified name. * * @param address the IPAddressName. */ public IPAddressName(byte[] address) { this.address = address; } protected static final char IPv4_LEN = 4; protected static final char IPv6_LEN = 16; /** * Create the IPAddressName object with a string representing the * ip address and a string representing the netmask, with encoding * having ip address encoding followed by the netmask encoding. * This form is needed for name constraints extension. * * @param s the ip address in the format: n.n.n.n or x:x:x:x:x:x:x:x (RFC 1884) * @param netmask the netmask address in the format: n.n.n.n or x:x:x:x:x:x:x:x (RFC 1884) */ public IPAddressName(String s, String netmask) { address = parseAddress(true, s); if (address.length == IPv4_LEN * 2) fillIPv4Address(netmask, address, address.length / 2); else fillIPv6Address(netmask, address, address.length / 2); } /** * IP address with CIDR netmask * * @param s a single IPv4 or IPv6 address * @param mask a CIDR netmask */ public IPAddressName(String s, CIDRNetmask mask) { address = parseAddress(true, s); mask.write(ByteBuffer.wrap( address, address.length / 2, address.length / 2)); } /** * Create the IPAddressName object with a string representing the * ip address. * * @param s the ip address in the format: n.n.n.n or x:x:x:x:x:x:x:x */ public IPAddressName(String s) { address = parseAddress(false, s); } /** * Initialise and return a byte[] and write the IP address into it. * If withNetmask == true, the byte[] will be double the size, * with the latter half uninitialised. * * @return byte[] of length 4 or 16 if withNetmask == false, * or length 8 or 32 if withNetmask == true. */ private static byte[] parseAddress(boolean withNetmask, String s) { if (s.indexOf(':') != -1) { byte[] address = new byte[IPv6_LEN * (withNetmask ? 2 : 1)]; fillIPv6Address(s, address, 0); return address; } else { byte[] address = new byte[IPv4_LEN * (withNetmask ? 2 : 1)]; fillIPv4Address(s, address, 0); return address; } } /** * Return the type of the GeneralName. */ @Override public int getType() { return (GeneralNameInterface.NAME_IP); } @Override public boolean validSingle() { return address.length == IPv4_LEN || address.length == IPv6_LEN; } @Override public boolean validSubtree() { return address.length == 2*IPv4_LEN || address.length == 2*IPv6_LEN; } /** * Encode the IPAddress name into the DerOutputStream. * * @param out the DER stream to encode the IPAddressName to. * @exception IOException on encoding errors. */ @Override public void encode(DerOutputStream out) throws IOException { out.putOctetString(address); } /** * Return a printable string of IPaddress */ @Override public String toString() { StringBuilder r = new StringBuilder("IPAddress: "); ByteBuffer buf = ByteBuffer.wrap(address); if (address.length == IPv4_LEN) { writeIPv4(r, buf); } else if (address.length == IPv4_LEN * 2) { writeIPv4(r, buf); r.append(","); writeIPv4(r, buf); } else if (address.length == IPv6_LEN) { writeIPv6(r, buf); } else if (address.length == IPv6_LEN * 2) { writeIPv6(r, buf); r.append(","); writeIPv6(r, buf); } else { // shouldn't be possible r.append("0.0.0.0"); } return r.toString(); } private static void writeIPv4(StringBuilder r, ByteBuffer buf) { for (int i = 0; i < 4; i++) { if (i > 0) r.append("."); r.append(buf.get() & 0xff); } } private static void writeIPv6(StringBuilder r, ByteBuffer buf) { for (int i = 0; i < 8; i++) { if (i > 0) r.append(":"); r.append(Integer.toHexString(read16BitInt(buf))); } } /** * Read big-endian 16-bit int from buffer (advancing cursor) */ private static int read16BitInt(ByteBuffer buf) { return ((buf.get() & 0xff) << 8) + (buf.get() & 0xff); } /** * Gets an IP v4 address in the form n.n.n.n. */ public static int fillIPv4Address(String s, byte[] address, int start) { StringTokenizer st = new StringTokenizer(s, "."); int nt = st.countTokens(); if (nt != IPv4_LEN) throw new InvalidIPAddressException(s); try { int end = start + nt; for (int i = start; i < end; i++) { // parse token into Integer then downcast into byte to avoid NumberFormatException address[i] = (byte) Integer.parseInt(st.nextToken()); } } catch (NumberFormatException e) { throw new InvalidIPAddressException(s); } return nt; } /** * Gets an IP address in the forms as defined in RFC1884:
*

    *
  • x:x:x:x:x:x:x:x *
  • ...::xxx (using :: shorthand) *
  • ...:n.n.n.n (with n.n.n.n at the end) *
*/ public static int fillIPv6Address(String s, byte[] address, int start) { int lastcolon = -2; int end = start + 16; int idx = start; for (int i = start; i < address.length; i++) address[i] = 0; if (s.indexOf('.') != -1) { // has n.n.n.n at the end lastcolon = s.lastIndexOf(':'); if (lastcolon == -1) throw new InvalidIPAddressException(s); end -= 4; fillIPv4Address(s.substring(lastcolon + 1), address, end); } try { String s1 = s; if (lastcolon != -2) s1 = s.substring(0, lastcolon + 1); int lastDoubleColon = s1.indexOf("::"); String l = s1, r = null; StringTokenizer lt = null, rt = null; if (lastDoubleColon != -1) { l = s1.substring(0, lastDoubleColon); r = s1.substring(lastDoubleColon + 2); if (l.length() == 0) l = null; if (r.length() == 0) r = null; } int at = 0; if (l != null) { lt = new StringTokenizer(l, ":", false); at += lt.countTokens(); } if (r != null) { rt = new StringTokenizer(r, ":", false); at += rt.countTokens(); } if (at > 8 || (lastcolon != -2 && (at > 6 || (lastDoubleColon == -1 && at != 6)))) throw new InvalidIPAddressException(s); if (l != null) { while (lt.hasMoreTokens()) { String tok = lt.nextToken(); int j = Integer.parseInt(tok, 16); address[idx++] = (byte) ((j >> 8) & 0xFF); address[idx++] = (byte) (j & 0xFF); } } if (r != null) { idx = end - (rt.countTokens() * 2); while (rt.hasMoreTokens()) { String tok = rt.nextToken(); int j = Integer.parseInt(tok, 16); address[idx++] = (byte) ((j >> 8) & 0xFF); address[idx++] = (byte) (j & 0xFF); } } } catch (NumberFormatException e) { throw new InvalidIPAddressException(s); } return 16; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/InvalidIPAddressException.java000066400000000000000000000027661412550063600320460ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; public class InvalidIPAddressException extends RuntimeException { /** * */ private static final long serialVersionUID = -1601934234587845028L; public InvalidIPAddressException() { super(); } public InvalidIPAddressException(String ip) { super("Invalid IP Address '" + ip + "'"); } public InvalidIPAddressException(String ip, Throwable cause) { super("Invalid IP Address '" + ip + "'", cause); } public InvalidIPAddressException(String ip, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super("Invalid IP Address '" + ip + "'", cause, enableSuppression, writableStackTrace); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/InvalidNetmaskException.java000066400000000000000000000025431412550063600316230ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2018 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; public class InvalidNetmaskException extends RuntimeException { public InvalidNetmaskException(String netmask) { super("Invalid netmask (" + netmask + ")"); } public InvalidNetmaskException(String netmask, Throwable cause) { super("Invalid netmask (" + netmask + ")", cause); } public InvalidNetmaskException(String netmask, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super("Invalid netmask (" + netmask + ")", cause, enableSuppression, writableStackTrace); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/InvalidityDateExtension.java000066400000000000000000000174651412550063600316530ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.security.cert.CertificateException; import java.util.Date; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * Represent the CRL Invalidity Date Extension. * *

* This CRL entry extension, if present, provides the date on which it is known or suspected that the private key was * compromised or that the certificate otherwise became invalid. Invalidity date may be earlier than the revocation * date. * * @see Extension * @see CertAttrSet */ public class InvalidityDateExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 2191026017389643053L; /** * Attribute name. */ public static final String NAME = "InvalidityDate"; public static final String INVALIDITY_DATE = "value"; /** * The Object Identifier for this extension. */ public static final String OID = "2.5.29.24"; private Date invalidityDate = null; static { try { OIDMap.addAttribute(InvalidityDateExtension.class.getName(), OID, NAME); } catch (CertificateException e) { } } // Encode this extension value private void encodeThis() throws IOException { if (invalidityDate == null) throw new IOException("Unintialized invalidity date extension"); try (DerOutputStream os = new DerOutputStream()) { os.putGeneralizedTime(this.invalidityDate); this.extensionValue = os.toByteArray(); } } /** * Create a InvalidityDateExtension with the date. * The criticality is set to false. * * @param dateOfInvalidity the value to be set for the extension. */ public InvalidityDateExtension(Date dateOfInvalidity) throws IOException { this.invalidityDate = dateOfInvalidity; this.extensionId = PKIXExtensions.InvalidityDate_Id; this.critical = false; encodeThis(); } /** * Create a InvalidityDateExtension with the date. * The criticality is set to false. * * @param critical true if the extension is to be treated as critical. * @param dateOfInvalidity the value to be set for the extension. */ public InvalidityDateExtension(Boolean critical, Date dateOfInvalidity) throws IOException { this.invalidityDate = dateOfInvalidity; this.extensionId = PKIXExtensions.InvalidityDate_Id; this.critical = critical.booleanValue(); encodeThis(); } /** * Create the extension from the passed DER encoded value of the same. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public InvalidityDateExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.InvalidityDate_Id; this.critical = critical.booleanValue(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); if (val.tag == DerValue.tag_GeneralizedTime) { DerInputStream derInputStream = new DerInputStream(val.toByteArray()); this.invalidityDate = derInputStream.getGeneralizedTime(); } else { throw new IOException("Invalid encoding for InvalidityDateExtension"); } } /** * Get the invalidity date. */ public Date getInvalidityDate() { return invalidityDate; } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { if (name.equalsIgnoreCase(INVALIDITY_DATE)) { if (!(obj instanceof Date)) { throw new IOException("Attribute must be of type Date."); } invalidityDate = (Date) obj; } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:InvalidityDate."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(INVALIDITY_DATE)) { if (invalidityDate == null) return null; else return invalidityDate; } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:InvalidityDate."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(INVALIDITY_DATE)) { invalidityDate = null; } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:InvalidityDate."); } } /** * Returns a printable representation of the InvalidityDateExtension. */ @Override public String toString() { String s = super.toString() + "Invalidity Date: " + ((invalidityDate == null) ? "" : invalidityDate.toString()) + "\n"; return (s); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { this.extensionId = PKIXExtensions.InvalidityDate_Id; this.critical = true; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(INVALIDITY_DATE); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/IssuerAlternativeNameExtension.java000066400000000000000000000172601412550063600332040ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This represents the Issuer Alternative Name Extension. * * This extension, if present, allows the issuer to specify multiple * alternative names. * *

* Extensions are represented as a sequence of the extension identifier (Object Identifier), a boolean flag stating * whether the extension is to be treated as being critical and the extension value itself (this is again a DER encoding * of the extension value). * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.7 * @see Extension * @see CertAttrSet */ public class IssuerAlternativeNameExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -269518027483586255L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.IssuerAlternativeName"; /** * Attribute names. */ public static final String NAME = "IssuerAlternativeName"; public static final String ISSUER_NAME = "issuer_name"; // private data members GeneralNames names; // Encode this extension private void encodeThis() throws IOException { DerOutputStream os = new DerOutputStream(); try { names.encode(os); } catch (GeneralNamesException e) { throw new IOException(e); } this.extensionValue = os.toByteArray(); } /** * Create a IssuerAlternativeNameExtension with the passed GeneralNames. * * @param critical true if the extension is to be treated as critical. * @param names the GeneralNames for the issuer. * @exception IOException on error. */ public IssuerAlternativeNameExtension(Boolean critical, GeneralNames names) throws IOException { this.names = names; this.extensionId = PKIXExtensions.IssuerAlternativeName_Id; this.critical = critical.booleanValue(); encodeThis(); } /** * Create a IssuerAlternativeNameExtension with the passed GeneralNames. * * @param names the GeneralNames for the issuer. * @exception IOException on error. */ public IssuerAlternativeNameExtension(GeneralNames names) throws IOException { this.names = names; this.extensionId = PKIXExtensions.IssuerAlternativeName_Id; this.critical = false; encodeThis(); } /** * Create a default IssuerAlternativeNameExtension. */ public IssuerAlternativeNameExtension() { extensionId = PKIXExtensions.IssuerAlternativeName_Id; critical = false; names = new GeneralNames(); } /** * Create the extension from the passed DER encoded value. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public IssuerAlternativeNameExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.IssuerAlternativeName_Id; this.critical = critical.booleanValue(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); try { names = new GeneralNames(val); } catch (GeneralNamesException e) { throw new IOException("IssuerAlternativeNameExtension: " + e, e); } } /** * Returns a printable representation of the IssuerAlternativeName. */ @Override public String toString() { if (names == null) return ""; String s = super.toString() + "IssuerAlternativeName [\n" + names.toString() + "]\n"; return (s); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the OutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on encoding error. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { extensionId = PKIXExtensions.IssuerAlternativeName_Id; critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { clearValue(); if (name.equalsIgnoreCase(ISSUER_NAME)) { if (!(obj instanceof GeneralNames)) { throw new IOException("Attribute value should be of" + " type GeneralNames."); } names = (GeneralNames) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:IssuerAlternativeName."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(ISSUER_NAME)) { return (names); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:IssuerAlternativeName."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(ISSUER_NAME)) { names = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:IssuerAlternativeName."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(ISSUER_NAME); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/IssuingDistributionPoint.java000066400000000000000000000265331412550063600320730ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import org.mozilla.jss.netscape.security.util.BitArray; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BOOLEAN; import org.mozilla.jss.asn1.EXPLICIT; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** *

 * issuingDistributionPoint ::= SEQUENCE {
 *         distributionPoint       [0] DistributionPointName OPTIONAL,
 *         onlyContainsUserCerts   [1] BOOLEAN DEFAULT FALSE,
 *         onlyContainsCACerts     [2] BOOLEAN DEFAULT FALSE,
 *         onlySomeReasons         [3] ReasonFlags OPTIONAL,
 *         indirectCRL             [4] BOOLEAN DEFAULT FALSE }
 *
 * DistributionPointName ::= CHOICE {
 *         fullName                [0]     GeneralNames,
 *         nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
 *
 * ReasonFlags ::= BIT STRING {
 *         unused                  (0),
 *         keyCompromise           (1),
 *         cACompromise            (2),
 *         affiliationChanged      (3),
 *         superseded              (4),
 *         cessationOfOperation    (5),
 *         certificateHold         (6) }
 *
 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
 *
 * GeneralName ::= CHOICE {
 *         otherName                       [0]     OtherName,
 *         rfc822Name                      [1]     IA5String,
 *         dNSName                         [2]     IA5String,
 *         x400Address                     [3]     ORAddress,
 *         directoryName                   [4]     Name,
 *         ediPartyName                    [5]     EDIPartyName,
 *         uniformResourceIdentifier       [6]     IA5String,
 *         iPAddress                       [7]     OCTET STRING,
 *         registeredID                    [8]     OBJECT IDENTIFIER}
 *
 * OtherName ::= SEQUENCE {
 *         type-id    OBJECT IDENTIFIER,
 *         value      [0] EXPLICIT ANY DEFINED BY type-id }
 *
 * EDIPartyName ::= SEQUENCE {
 *         nameAssigner            [0]     DirectoryString OPTIONAL,
 *         partyName               [1]     DirectoryString }
 *
 * RelativeDistinguishedName ::=
 *         SET OF AttributeTypeAndValue
 *
 * AttributeTypeAndValue ::= SEQUENCE {
 *         type     AttributeType,
 *         value    AttributeValue }
 *
 * AttributeType ::= OBJECT IDENTIFIER
 *
 * AttributeValue ::= ANY DEFINED BY AttributeType
 * 
* * See the documentation in CRLDistributionPoint for * the DistributionPointName and ReasonFlags ASN.1 types. */ public class IssuingDistributionPoint implements ASN1Value { // at most one of the following two may be specified. One or both can // be null. private GeneralNames fullName = null; private RDN relativeName = null; private boolean onlyContainsUserCerts = false; // DEFAULT FALSE private boolean onlyContainsCACerts = false; // DEFAULT FALSE private BitArray onlySomeReasons = null; // optional, may be null private boolean indirectCRL = false; // DEFAULT FALSE // cache encoding of fullName private ANY fullNameEncoding; /** * Returns the fullName of the DistributionPointName, which may be null. */ public GeneralNames getFullName() { return fullName; } /** * Returns the relativeName of the DistributionPointName, which may be null. */ public RDN getRelativeName() { return relativeName; } /** * Sets the fullName of the DistributionPointName. It may be set to null. * If it is set to a non-null value, relativeName will be * set to null, because at most one of these two attributes * can be specified at a time. * * @exception GeneralNamesException If an error occurs encoding the * name. */ public void setFullName(GeneralNames fullName) throws GeneralNamesException, IOException { this.fullName = fullName; if (fullName != null) { // encode the name to catch any problems with it DerOutputStream derOut = new DerOutputStream(); fullName.encode(derOut); try { ANY raw = new ANY(derOut.toByteArray()); ByteArrayOutputStream bos = new ByteArrayOutputStream(); raw.encodeWithAlternateTag(Tag.get(0), bos); fullNameEncoding = new ANY(bos.toByteArray()); } catch (InvalidBERException e) { // assume this won't happen, since it would imply a bug // in DerOutputStream throw new GeneralNamesException(e.toString()); } this.relativeName = null; } } /** * Sets the relativeName of the DistributionPointName. It may be set to null. * If it is set to a non-null value, fullName will be * set to null, because at most one of these two attributes * can be specified at a time. */ public void setRelativeName(RDN relativeName) { this.relativeName = relativeName; if (relativeName != null) { this.fullName = null; } } public boolean getOnlyContainsUserCerts() { return onlyContainsUserCerts; } public void setOnlyContainsUserCerts(boolean b) { onlyContainsUserCerts = b; } public boolean getOnlyContainsCACerts() { return onlyContainsCACerts; } public void setOnlyContainsCACerts(boolean b) { onlyContainsCACerts = b; } /** * Returns the reason flags for this distribution point. May be null. */ public BitArray getOnlySomeReasons() { return onlySomeReasons; } /** * Sets the reason flags for this distribution point. May be set to null. */ public void setOnlySomeReasons(BitArray reasons) { this.onlySomeReasons = reasons; } public boolean getIndirectCRL() { return indirectCRL; } public void setIndirectCRL(boolean b) { indirectCRL = b; } ///////////////////////////////////////////////////////////// // DER encoding ///////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); DerOutputStream derOut; try { // Encodes the DistributionPointName. Because DistributionPointName // is a CHOICE, the [0] tag is forced to be EXPLICIT. if (fullName != null) { EXPLICIT distPoint = new EXPLICIT(Tag.get(0), fullNameEncoding); seq.addElement(distPoint); } else if (relativeName != null) { derOut = new DerOutputStream(); relativeName.encode(derOut); ANY raw = new ANY(derOut.toByteArray()); ByteArrayOutputStream bos = new ByteArrayOutputStream(); raw.encodeWithAlternateTag(Tag.get(1), bos); ANY distPointName = new ANY(bos.toByteArray()); EXPLICIT distPoint = new EXPLICIT(Tag.get(0), distPointName); seq.addElement(distPoint); } if (onlyContainsUserCerts != false) { seq.addElement(Tag.get(1), new BOOLEAN(true)); } if (onlyContainsCACerts != false) { seq.addElement(Tag.get(2), new BOOLEAN(true)); } // Encodes the ReasonFlags. if (onlySomeReasons != null) { derOut = new DerOutputStream(); derOut.putUnalignedBitString(onlySomeReasons); ANY raw = new ANY(derOut.toByteArray()); ByteArrayOutputStream bos = new ByteArrayOutputStream(); raw.encodeWithAlternateTag(Tag.get(3), bos); ANY reasonEncoding = new ANY(bos.toByteArray()); seq.addElement(reasonEncoding); } if (indirectCRL != false) { seq.addElement(Tag.get(4), new BOOLEAN(true)); } seq.encode(implicitTag, ostream); } catch (InvalidBERException e) { // this shouldn't happen unless there is a bug in one of // the Sun encoding classes throw new IOException(e.toString()); } } public static void main(String args[]) { BufferedOutputStream bos = null; try { if (args.length != 1) { System.out.println("Usage: IssuingDistributionPoint "); System.exit(-1); } bos = new BufferedOutputStream( new FileOutputStream(args[0])); SEQUENCE idps = new SEQUENCE(); IssuingDistributionPoint idp = new IssuingDistributionPoint(); X500Name dn = new X500Name("CN=Skovw Wjasldk,E=nicolson@netscape.com" + ",OU=Certificate Server,O=Netscape,C=US"); GeneralNames generalNames = new GeneralNames(); generalNames.addElement(dn); idp.setFullName(generalNames); idps.addElement(idp); idp = new IssuingDistributionPoint(); URIName uri = new URIName("http://www.mycrl.com/go/here"); generalNames = new GeneralNames(); generalNames.addElement(uri); idp.setFullName(generalNames); idp.setOnlyContainsUserCerts(true); idp.setOnlyContainsCACerts(true); idp.setIndirectCRL(true); BitArray ba = new BitArray(5, new byte[] { (byte) 0x28 }); idp.setOnlySomeReasons(ba); idps.addElement(idp); idps.encode(bos); } catch (Exception e) { e.printStackTrace(); } finally { if (bos != null) { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } } } IssuingDistributionPointExtension.java000066400000000000000000000411611412550063600337030ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.cert.CertificateException; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.netscape.security.util.BitArray; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * A critical CRL extension that identifies the CRL distribution point * for a particular CRL * *
 * issuingDistributionPoint ::= SEQUENCE {
 *         distributionPoint       [0] DistributionPointName OPTIONAL,
 *         onlyContainsUserCerts   [1] BOOLEAN DEFAULT FALSE,
 *         onlyContainsCACerts     [2] BOOLEAN DEFAULT FALSE,
 *         onlySomeReasons         [3] ReasonFlags OPTIONAL,
 *         indirectCRL             [4] BOOLEAN DEFAULT FALSE }
 *
 * DistributionPointName ::= CHOICE {
 *         fullName                [0]     GeneralNames,
 *         nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
 *
 * ReasonFlags ::= BIT STRING {
 *         unused                  (0),
 *         keyCompromise           (1),
 *         cACompromise            (2),
 *         affiliationChanged      (3),
 *         superseded              (4),
 *         cessationOfOperation    (5),
 *         certificateHold         (6) }
 *
 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
 *
 * GeneralName ::= CHOICE {
 *         otherName                       [0]     OtherName,
 *         rfc822Name                      [1]     IA5String,
 *         dNSName                         [2]     IA5String,
 *         x400Address                     [3]     ORAddress,
 *         directoryName                   [4]     Name,
 *         ediPartyName                    [5]     EDIPartyName,
 *         uniformResourceIdentifier       [6]     IA5String,
 *         iPAddress                       [7]     OCTET STRING,
 *         registeredID                    [8]     OBJECT IDENTIFIER}
 *
 * OtherName ::= SEQUENCE {
 *         type-id    OBJECT IDENTIFIER,
 *         value      [0] EXPLICIT ANY DEFINED BY type-id }
 *
 * EDIPartyName ::= SEQUENCE {
 *         nameAssigner            [0]     DirectoryString OPTIONAL,
 *         partyName               [1]     DirectoryString }
 *
 * RelativeDistinguishedName ::=
 *         SET OF AttributeTypeAndValue
 *
 * AttributeTypeAndValue ::= SEQUENCE {
 *         type     AttributeType,
 *         value    AttributeValue }
 *
 * AttributeType ::= OBJECT IDENTIFIER
 *
 * AttributeValue ::= ANY DEFINED BY AttributeType
 * 
*/ public class IssuingDistributionPointExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -1281544042375527550L; /** * The Object Identifier for this extension. */ public static final String OID = "2.5.29.28"; /** * Attribute names. */ public static final String NAME = "IssuingDistributionPoint"; public static final String ISSUING_DISTRIBUTION_POINT = "issuing_distribution_point"; // Private data members private IssuingDistributionPoint issuingDistributionPoint = null; // Cached DER-encoding to improve performance. private byte[] cachedEncoding = null; static { try { OIDMap.addAttribute(IssuingDistributionPointExtension.class.getName(), OID, NAME); } catch (CertificateException e) { } } /** * This constructor is very important, since it will be called * by the system. */ public IssuingDistributionPointExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.IssuingDistributionPoint_Id; this.critical = critical.booleanValue(); this.extensionValue = ((byte[]) value).clone(); byte[] extValue = this.extensionValue; issuingDistributionPoint = new IssuingDistributionPoint(); DerValue val = new DerValue(extValue); if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding of IssuingDistributionPoint"); } while (val.data.available() != 0) { DerValue opt = val.data.getDerValue(); if (opt != null) { for (int i = 0; i < 5; i++) { if (opt.isContextSpecific((byte) i)) { if ((i == 0 && opt.isConstructed() && opt.data.available() != 0) || (i != 0 && (!opt.isConstructed()) && opt.data.available() != 0)) { if (i == 0) { DerValue opt1 = opt.data.getDerValue(); if (opt1 != null) { if (opt1.isContextSpecific((byte) 0)) { if (opt1.isConstructed() && opt1.data.available() != 0) { opt1.resetTag(DerValue.tag_Sequence); try { GeneralNames fullName = new GeneralNames(opt1); if (fullName != null) { issuingDistributionPoint.setFullName(fullName); } } catch (GeneralNamesException e) { throw new IOException("Invalid encoding of IssuingDistributionPoint " + e, e); } catch (IOException e) { throw new IOException("Invalid encoding of IssuingDistributionPoint " + e, e); } } else { throw new IOException("Invalid encoding of IssuingDistributionPoint"); } } else if (opt1.isContextSpecific((byte) 1)) { if (opt1.isConstructed() && opt1.data.available() != 0) { opt1.resetTag(DerValue.tag_Set); try { RDN relativeName = new RDN(opt1); if (relativeName != null) { issuingDistributionPoint.setRelativeName(relativeName); } } catch (IOException e) { throw new IOException("Invalid encoding of IssuingDistributionPoint " + e, e); } } else { throw new IOException("Invalid encoding of IssuingDistributionPoint"); } } } } else if (i == 3) { opt.resetTag(DerValue.tag_BitString); try { BitArray reasons = opt.getUnalignedBitString(); if (reasons == null) { throw new IOException("Unable to get the unaligned bit string."); } issuingDistributionPoint.setOnlySomeReasons(reasons); @SuppressWarnings("unused") byte[] a = reasons.toByteArray(); // check for errors } catch (IOException e) { throw new IOException("Invalid encoding of IssuingDistributionPoint " + e, e); } } else { opt.resetTag(DerValue.tag_Boolean); try { boolean b = opt.getBoolean(); if (i == 1) { issuingDistributionPoint.setOnlyContainsUserCerts(b); } else if (i == 2) { issuingDistributionPoint.setOnlyContainsCACerts(b); } else if (i == 4) { issuingDistributionPoint.setIndirectCRL(b); } } catch (IOException e) { throw new IOException("Invalid encoding of IssuingDistributionPoint " + e, e); } } } else { throw new IOException("Invalid encoding of IssuingDistributionPoint"); } } } } else { throw new IOException("Invalid encoding of IssuingDistributionPoint"); } } } /** * Creates a new IssuingDistributionPoint extension, with the given * issuing distribution point as the first element. */ public IssuingDistributionPointExtension(IssuingDistributionPoint idp) { this.extensionId = PKIXExtensions.IssuingDistributionPoint_Id; this.critical = true; issuingDistributionPoint = idp; } /** * Returns the issuing distribution point. */ public IssuingDistributionPoint getIssuingDistributionPoint() { return issuingDistributionPoint; } /** * Sets the criticality of this extension. PKIX dictates that this * extension SHOULD be critical, so applications can make it not critical * if they have a very good reason. By default, the extension is critical. */ @Override public void setCritical(boolean critical) { this.critical = critical; } /** * Gets the criticality of this extension. PKIX dictates that this * extension SHOULD be critical, so by default, the extension is critical. */ public boolean getCritical(boolean critical) { return this.critical; } /** * Encodes this extension to the given DerOutputStream. * This method re-encodes each time it is called, so it is not very * efficient. */ @Override public void encode(DerOutputStream out) throws IOException { extensionValue = ASN1Util.encode(issuingDistributionPoint); super.encode(out); } /** * Should be called if any change is made to this data structure * so that the cached DER encoding can be discarded. */ public void flushCachedEncoding() { cachedEncoding = null; } /** * Returns a printable representation of the IssuingDistributionPointExtension */ @Override public String toString() { return NAME; } /** * DER-encodes this extension to the given OutputStream. */ @Override public void encode(OutputStream ostream) throws CertificateException, IOException { if (cachedEncoding == null) { // only re-encode if necessary DerOutputStream tmp = new DerOutputStream(); encode(tmp); cachedEncoding = tmp.toByteArray(); } ostream.write(cachedEncoding); } @Override public void decode(InputStream in) throws CertificateException, IOException { throw new IOException("Not supported"); } @Override public void set(String name, Object obj) throws CertificateException, IOException { if (name.equalsIgnoreCase(ISSUING_DISTRIBUTION_POINT)) { if (!(obj instanceof IssuingDistributionPoint)) { throw new IOException("Attribute value should be of type IssuingDistributionPoint."); } issuingDistributionPoint = (IssuingDistributionPoint) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:IssuingDistributionPointExtension"); } } @Override public Object get(String name) throws CertificateException, IOException { if (name.equalsIgnoreCase(ISSUING_DISTRIBUTION_POINT)) { return issuingDistributionPoint; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:IssuingDistributionPointExtension"); } } @Override public void delete(String name) throws CertificateException, IOException { if (name.equalsIgnoreCase(ISSUING_DISTRIBUTION_POINT)) { issuingDistributionPoint = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:IssuingDistributionPointExtension"); } } @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(ISSUING_DISTRIBUTION_POINT); return (elements.elements()); // return (new Vector()).elements(); } @Override public String getName() { return NAME; } /** * Test driver. */ public static void main(String args[]) { BufferedOutputStream bos = null; try { if (args.length != 1) { System.out.println("Usage: IssuingDistributionPointExtension " + ""); System.exit(-1); } bos = new BufferedOutputStream( new FileOutputStream(args[0])); // URI only IssuingDistributionPoint idp = new IssuingDistributionPoint(); URIName uri = new URIName("http://www.mycrl.com/go/here"); GeneralNames generalNames = new GeneralNames(); generalNames.addElement(uri); idp.setFullName(generalNames); IssuingDistributionPointExtension idpExt = new IssuingDistributionPointExtension(idp); // DN only idp = new IssuingDistributionPoint(); X500Name dn = new X500Name("CN=Otis Smith,E=otis@fedoraproject.org" + ",OU=Certificate Server,O=Fedora,C=US"); generalNames = new GeneralNames(); generalNames.addElement(dn); idp.setFullName(generalNames); idpExt.set(IssuingDistributionPointExtension.ISSUING_DISTRIBUTION_POINT, idp); // DN + reason BitArray ba = new BitArray(5, new byte[] { (byte) 0x28 }); idp = new IssuingDistributionPoint(); idp.setFullName(generalNames); idp.setOnlySomeReasons(ba); idpExt.set(IssuingDistributionPointExtension.ISSUING_DISTRIBUTION_POINT, idp); // relative DN + reason + crlIssuer idp = new IssuingDistributionPoint(); RDN rdn = new RDN("OU=foobar dept"); idp.setRelativeName(rdn); idp.setOnlySomeReasons(ba); idp.setOnlyContainsCACerts(true); idp.setOnlyContainsUserCerts(true); idp.setIndirectCRL(true); idpExt.set(IssuingDistributionPointExtension.ISSUING_DISTRIBUTION_POINT, idp); idpExt.setCritical(false); idpExt.encode(bos); } catch (Exception e) { e.printStackTrace(); } finally { if (bos != null) { try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/KeyIdentifier.java000066400000000000000000000051331412550063600275640ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * Represent the Key Identifier ASN.1 object. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.4 */ public class KeyIdentifier implements java.io.Serializable { /** * */ private static final long serialVersionUID = 2412286879441154979L; private byte[] octetString; /** * Create a KeyIdentifier with the passed bit settings. * * @param octetString the octet string identifying the key identifier. */ public KeyIdentifier(byte[] octetString) { this.octetString = octetString; } /** * Create a KeyIdentifier from the DER encoded value. * * @param val the DerValue */ public KeyIdentifier(DerValue val) throws IOException { octetString = val.getOctetString(); } /** * Return the value of the KeyIdentifier as byte array. */ public byte[] getIdentifier() { return octetString.clone(); } /** * Returns a printable representation of the KeyUsage. */ @Override public String toString() { org.mozilla.jss.netscape.security.util.PrettyPrintFormat pp = new org.mozilla.jss.netscape.security.util.PrettyPrintFormat(" ", 20); String octetbits = pp.toHexString(octetString); String s = "KeyIdentifier [\n"; s += octetbits; s += "]\n"; return (s); } /** * Write the KeyIdentifier to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException */ void encode(DerOutputStream out) throws IOException { out.putOctetString(octetString); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/KeyUsageExtension.java000066400000000000000000000344261412550063600304520ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.BitArray; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * Represent the Key Usage Extension. * *

* This extension, if present, defines the purpose (e.g., encipherment, signature, certificate signing) of the key * contained in the certificate. The usage restriction might be employed when a multipurpose key is to be restricted * (e.g., when an RSA key should be used only for signing or only for key encipherment). * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.9 * @see Extension * @see CertAttrSet */ public class KeyUsageExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 2899719374157256708L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.KeyUsage"; /** * Attribute names. */ public static final String NAME = "KeyUsage"; public static final String DIGITAL_SIGNATURE = "digital_signature"; public static final String NON_REPUDIATION = "non_repudiation"; public static final String KEY_ENCIPHERMENT = "key_encipherment"; public static final String DATA_ENCIPHERMENT = "data_encipherment"; public static final String KEY_AGREEMENT = "key_agreement"; public static final String KEY_CERTSIGN = "key_certsign"; public static final String CRL_SIGN = "crl_sign"; public static final String ENCIPHER_ONLY = "encipher_only"; public static final String DECIPHER_ONLY = "decipher_only"; public static final int DIGITAL_SIGNATURE_BIT = 0; public static final int NON_REPUDIATION_BIT = 1; public static final int KEY_ENCIPHERMENT_BIT = 2; public static final int DATA_ENCIPHERMENT_BIT = 3; public static final int KEY_AGREEMENT_BIT = 4; public static final int KEY_CERTSIGN_BIT = 5; public static final int CRL_SIGN_BIT = 6; public static final int ENCIPHER_ONLY_BIT = 7; public static final int DECIPHER_ONLY_BIT = 8; public static final int NBITS = 9; public static String[] names = new String[NBITS]; static { names[DIGITAL_SIGNATURE_BIT] = DIGITAL_SIGNATURE; names[NON_REPUDIATION_BIT] = NON_REPUDIATION; names[KEY_ENCIPHERMENT_BIT] = KEY_ENCIPHERMENT; names[DATA_ENCIPHERMENT_BIT] = DATA_ENCIPHERMENT; names[KEY_AGREEMENT_BIT] = KEY_AGREEMENT; names[KEY_CERTSIGN_BIT] = KEY_CERTSIGN; names[CRL_SIGN_BIT] = CRL_SIGN; names[ENCIPHER_ONLY_BIT] = ENCIPHER_ONLY; names[DECIPHER_ONLY_BIT] = DECIPHER_ONLY; } // Private data members private boolean[] bitString; // Encode this extension value private void encodeThis() throws IOException { try (DerOutputStream os = new DerOutputStream()) { os.putUnalignedBitString(this.bitString); this.extensionValue = os.toByteArray(); } } /** * Check if bit is set. * * @param position the position in the bit string to check. */ private boolean isSet(int position) { if (bitString.length <= position) return false; return bitString[position]; } /** * Set the bit at the specified position. */ private void set(int position, boolean val) { // enlarge bitString if necessary if (position >= bitString.length) { boolean[] tmp = new boolean[position + 1]; System.arraycopy(bitString, 0, tmp, 0, bitString.length); bitString = tmp; } bitString[position] = val; } /** * Create a KeyUsageExtension with the passed bit settings. The criticality * is set to true. * * @param bitString the bits to be set for the extension. */ public KeyUsageExtension(boolean critical, byte[] bitString) throws IOException { this.bitString = new BitArray(bitString.length * 8, bitString).toBooleanArray(); this.extensionId = PKIXExtensions.KeyUsage_Id; this.critical = critical; encodeThis(); } public KeyUsageExtension(byte[] bitString) throws IOException { this.bitString = new BitArray(bitString.length * 8, bitString).toBooleanArray(); this.extensionId = PKIXExtensions.KeyUsage_Id; this.critical = true; encodeThis(); } /** * Create a KeyUsageExtension with the passed bit settings. The criticality * is set to true. * * @param bitString the bits to be set for the extension. */ public KeyUsageExtension(boolean critical, boolean[] bitString) throws IOException { this.bitString = bitString; this.extensionId = PKIXExtensions.KeyUsage_Id; this.critical = critical; encodeThis(); } public KeyUsageExtension(boolean[] bitString) throws IOException { this.bitString = bitString; this.extensionId = PKIXExtensions.KeyUsage_Id; this.critical = true; encodeThis(); } /** * Create a KeyUsageExtension with the passed bit settings. The criticality * is set to true. * * @param bitString the bits to be set for the extension. */ public KeyUsageExtension(BitArray bitString) throws IOException { this.bitString = bitString.toBooleanArray(); this.extensionId = PKIXExtensions.KeyUsage_Id; this.critical = true; encodeThis(); } /** * Create the extension from the passed DER encoded value of the same. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public KeyUsageExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.KeyUsage_Id; this.critical = critical.booleanValue(); /* * The following check should be activated again after * the PKIX profiling work becomes standard and the check * is not a barrier to interoperability ! * if (!this.critical) { * throw new IOException("KeyUsageExtension not marked critical," * + " invalid profile."); * } */ int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); BitArray bitArray = val.getUnalignedBitString(); if (bitArray == null) { throw new IOException("Invalid bit string"); } this.bitString = bitArray.toBooleanArray(); } /** * Create a default key usage. */ public KeyUsageExtension() { extensionId = PKIXExtensions.KeyUsage_Id; critical = true; bitString = new boolean[0]; } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { clearValue(); if (!(obj instanceof Boolean)) { throw new IOException("Attribute must be of type Boolean."); } boolean val = ((Boolean) obj).booleanValue(); if (name.equalsIgnoreCase(DIGITAL_SIGNATURE)) { set(0, val); } else if (name.equalsIgnoreCase(NON_REPUDIATION)) { set(1, val); } else if (name.equalsIgnoreCase(KEY_ENCIPHERMENT)) { set(2, val); } else if (name.equalsIgnoreCase(DATA_ENCIPHERMENT)) { set(3, val); } else if (name.equalsIgnoreCase(KEY_AGREEMENT)) { set(4, val); } else if (name.equalsIgnoreCase(KEY_CERTSIGN)) { set(5, val); } else if (name.equalsIgnoreCase(CRL_SIGN)) { set(6, val); } else if (name.equalsIgnoreCase(ENCIPHER_ONLY)) { set(7, val); } else if (name.equalsIgnoreCase(DECIPHER_ONLY)) { set(8, val); } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:KeyUsage."); } encodeThis(); } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(DIGITAL_SIGNATURE)) { return Boolean.valueOf(isSet(0)); } else if (name.equalsIgnoreCase(NON_REPUDIATION)) { return Boolean.valueOf(isSet(1)); } else if (name.equalsIgnoreCase(KEY_ENCIPHERMENT)) { return Boolean.valueOf(isSet(2)); } else if (name.equalsIgnoreCase(DATA_ENCIPHERMENT)) { return Boolean.valueOf(isSet(3)); } else if (name.equalsIgnoreCase(KEY_AGREEMENT)) { return Boolean.valueOf(isSet(4)); } else if (name.equalsIgnoreCase(KEY_CERTSIGN)) { return Boolean.valueOf(isSet(5)); } else if (name.equalsIgnoreCase(CRL_SIGN)) { return Boolean.valueOf(isSet(6)); } else if (name.equalsIgnoreCase(ENCIPHER_ONLY)) { return Boolean.valueOf(isSet(7)); } else if (name.equalsIgnoreCase(DECIPHER_ONLY)) { return Boolean.valueOf(isSet(8)); } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:KeyUsage."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(DIGITAL_SIGNATURE)) { set(0, false); } else if (name.equalsIgnoreCase(NON_REPUDIATION)) { set(1, false); } else if (name.equalsIgnoreCase(KEY_ENCIPHERMENT)) { set(2, false); } else if (name.equalsIgnoreCase(DATA_ENCIPHERMENT)) { set(3, false); } else if (name.equalsIgnoreCase(KEY_AGREEMENT)) { set(4, false); } else if (name.equalsIgnoreCase(KEY_CERTSIGN)) { set(5, false); } else if (name.equalsIgnoreCase(CRL_SIGN)) { set(6, false); } else if (name.equalsIgnoreCase(ENCIPHER_ONLY)) { set(7, false); } else if (name.equalsIgnoreCase(DECIPHER_ONLY)) { set(8, false); } else { throw new IOException("Attribute name not recognized by" + " CertAttrSet:KeyUsage."); } } /** * Returns a printable representation of the KeyUsage. */ @Override public String toString() { String s = super.toString() + "KeyUsage [\n"; try { if (isSet(0)) { s += " DigitalSignature\n"; } if (isSet(1)) { s += " Non_repudiation\n"; } if (isSet(2)) { s += " Key_Encipherment\n"; } if (isSet(3)) { s += " Data_Encipherment\n"; } if (isSet(4)) { s += " Key_Agreement\n"; } if (isSet(5)) { s += " Key_CertSign\n"; } if (isSet(6)) { s += " Crl_Sign\n"; } if (isSet(7)) { s += " Encipher_Only\n"; } if (isSet(8)) { s += " Decipher_Only\n"; } } catch (ArrayIndexOutOfBoundsException ex) { } s += "]\n"; return (s); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { this.extensionId = PKIXExtensions.KeyUsage_Id; this.critical = true; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(DIGITAL_SIGNATURE); elements.addElement(NON_REPUDIATION); elements.addElement(KEY_ENCIPHERMENT); elements.addElement(DATA_ENCIPHERMENT); elements.addElement(KEY_AGREEMENT); elements.addElement(KEY_CERTSIGN); elements.addElement(CRL_SIGN); elements.addElement(ENCIPHER_ONLY); elements.addElement(DECIPHER_ONLY); return (elements.elements()); } public boolean[] getBits() { return bitString.clone(); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/LdapDNStrConverter.java000066400000000000000000000100711412550063600305110ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; /** * Abstract class that converts a Ldap DN String to an X500Name, RDN or AVA * and vice versa, except the string is a java string in unicode. * * @author Lily Hsiao, Slava Galperin at Netscape Communications, Inc. */ public abstract class LdapDNStrConverter { // // public parsing methods. // /** * Converts a Ldap DN string to a X500Name object. * * @param dn a Ldap DN String. * * @return an X500Name object for the Ldap DN String. */ public abstract X500Name parseDN(String dn) throws IOException; /** * Like parseDN with a specified DER encoding order for Directory Strings. */ public abstract X500Name parseDN(String dn, byte[] tags) throws IOException; /** * Converts a Ldap DN string to a RDN object. * * @param rdn a Ldap DN String * * @return an RDN object. */ public abstract RDN parseRDN(String rdn) throws IOException; /** * Like parseRDN with a specified DER encoding order for Directory Strings. */ public abstract RDN parseRDN(String rdn, byte[] tags) throws IOException; /** * Converts a Ldap DN string to a AVA object. * * @param ava a Ldap DN string. * @return an AVA object. */ public abstract AVA parseAVA(String ava) throws IOException; /** * Like parseAVA with a specified DER encoding order for Directory Strings. */ public abstract AVA parseAVA(String rdn, byte[] tags) throws IOException; // // public encoding methods. // /** * Converts a X500Name object to a Ldap dn string. * * @param dn an X500Name object. * @return a Ldap DN String. */ public abstract String encodeDN(X500Name dn) throws IOException; /** * Converts an RDN object to a Ldap dn string. * * @param rdn an RDN object. * @return a Ldap dn string. */ public abstract String encodeRDN(RDN rdn) throws IOException; /** * Converts an AVA object to a Ldap dn string. * * @param ava An AVA object. * @return A Ldap dn string. */ public abstract String encodeAVA(AVA ava) throws IOException; // // public static methods // /** * Gets a global default Ldap DN String converter. * Currently it is LdapV3DNStrConverter object using the default * X500NameAttrMap and accepts unknown OIDs. * * @see LdapV3DNStrConverter * * @return The global default LdapDNStrConverter instance. */ public static LdapDNStrConverter getDefault() { return defaultConverter; } /** * Set the global default LdapDNStrConverter object. * * @param defConverter A LdapDNStrConverter object to become * the global default. */ public static void setDefault(LdapDNStrConverter defConverter) { if (defConverter == null) throw new IllegalArgumentException( "The default Ldap DN String converter cannot be set to null."); defaultConverter = defConverter; } // // private static variables // private static LdapDNStrConverter defaultConverter = new LdapV3DNStrConverter(); } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/LdapV3DNStrConverter.java000066400000000000000000000667241412550063600307420ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.ByteArrayOutputStream; import java.io.CharArrayWriter; import java.io.IOException; import java.io.PushbackReader; import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.UnsupportedCharsetException; import java.util.Arrays; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** * A converter that converts Ldap v3 DN strings as specified in * draft-ietf-asid-ldapv3-dn-03.txt to a X500Name, RDN or AVA and * vice versa. * * @see LdapDNStrConverter * @see X500Name * @see RDN * @see AVA * @see X500NameAttrMap * * @author Lily Hsiao, Slava Galperin at Netscape Communications, Inc. */ public class LdapV3DNStrConverter extends LdapDNStrConverter { // // Constructors // /** * Constructs a LdapV3DNStrConverter using the global default * X500NameAttrMap and accept OIDs not in the default X500NameAttrMap. * * @see X500NameAttrMap */ public LdapV3DNStrConverter() { attrMap = X500NameAttrMap.getDefault(); acceptUnknownOids = true; } /** * Constructs a LdapV3DNStrConverter using the specified X500NameAttrMap * and a boolean indicating whether to accept OIDs not listed in the * X500NameAttrMap. * * @param attributeMap a X500NameAttrMap * @param doAcceptUnknownOids whether to convert unregistered OIDs * (oids not in the X500NameAttrMap) * @see X500NameAttrMap */ public LdapV3DNStrConverter(X500NameAttrMap attributeMap, boolean doAcceptUnknownOids) { attrMap = attributeMap; acceptUnknownOids = doAcceptUnknownOids; } // // public parsing methods // From LdapDNStrConverter interface // /** * Parse a Ldap v3 DN string to a X500Name. * * @param dn a LDAP v3 DN String * @return a X500Name * @exception IOException if an error occurs during the conversion. */ @Override public X500Name parseDN(String dn) throws IOException { return parseDN(dn, null); } /** * Like parseDN(String) with a DER encoding order given as argument for * Directory Strings. */ @Override public X500Name parseDN(String dn, byte[] encodingOrder) throws IOException { StringReader dn_reader = new StringReader(dn); PushbackReader in = new PushbackReader(dn_reader, 5); return parseDN(in, encodingOrder); } /** * Parse a Ldap v3 DN string with a RDN component to a RDN * * @param rdn a LDAP v3 DN String * @return a RDN * @exception IOException if an error occurs during the conversion. */ @Override public RDN parseRDN(String rdn) throws IOException { return parseRDN(rdn, null); } /** * Like parseRDN(String) with a DER encoding order given as argument for * Directory Strings. */ @Override public RDN parseRDN(String rdn, byte[] encodingOrder) throws IOException { StringReader rdn_reader = new StringReader(rdn); PushbackReader in = new PushbackReader(rdn_reader, 5); return parseRDN(in, null); } /** * Parse a Ldap v3 DN string with a AVA component to a AVA. * * @param ava a LDAP v3 DN string * @return a AVA */ @Override public AVA parseAVA(String ava) throws IOException { return parseAVA(ava, null); } /** * Like parseDN(String) with a DER encoding order given as argument for * Directory Strings. */ @Override public AVA parseAVA(String ava, byte[] encodingOrder) throws IOException { StringReader ava_reader = new StringReader(ava); PushbackReader in = new PushbackReader(ava_reader, 5); return parseAVA(in, encodingOrder); } // // public parsing methods called by other methods. // /** * Parses a Ldap DN string in a string reader to a X500Name. * * @param in Pushback string reader for a Ldap DN string. * The pushback reader must have a pushback buffer * {@literal size > 2}. * * @return a X500Name * * @exception IOException if any reading or parsing error occurs. */ public X500Name parseDN(PushbackReader in) throws IOException { return parseDN(in, null); } /** * Like parseDN(PushbackReader in) with a DER encoding order given as * argument for Directory Strings. */ public X500Name parseDN(PushbackReader in, byte[] encodingOrder) throws IOException { RDN rdn; int lastChar; Vector rdnVector = new Vector(); RDN names[]; int i, j; do { rdn = parseRDN(in, encodingOrder); rdnVector.addElement(rdn); lastChar = in.read(); } while (lastChar == ',' || lastChar == ';'); names = new RDN[rdnVector.size()]; for (i = 0, j = rdnVector.size() - 1; i < rdnVector.size(); i++, j--) names[j] = rdnVector.elementAt(i); return new X500Name(names); } /** * Parses Ldap DN string with a rdn component * from a string reader to a RDN. The string reader will point * to the separator after the rdn component or -1 if at end of string. * * @param in Pushback string reader containing a Ldap DN string with * at least one rdn component. * The pushback reader must have a pushback buffer * {@literal size > 2}. * * @return RDN object of the first rdn component in the Ldap DN string. * * @exception IOException if any read or parse error occurs. */ public RDN parseRDN(PushbackReader in) throws IOException { return parseRDN(in, null); } /** * Like parseRDN(PushbackReader) with a DER encoding order given as * argument for Directory Strings. */ public RDN parseRDN(PushbackReader in, byte[] encodingOrder) throws IOException { Vector avaVector = new Vector(); AVA ava; int lastChar; AVA assertion[]; do { ava = parseAVA(in, encodingOrder); avaVector.addElement(ava); lastChar = in.read(); } while (lastChar == '+'); if (lastChar != -1) in.unread(lastChar); assertion = new AVA[avaVector.size()]; for (int i = 0; i < avaVector.size(); i++) assertion[i] = avaVector.elementAt(i); return new RDN(assertion); } /** * Parses a Ldap DN string with a AVA component * from a string reader to an AVA. The string reader will point * to the AVA separator after the ava string or -1 if end of string. * * @param in a Pushback reader containg a Ldap string with * at least one AVA component. * The Pushback reader must have a pushback buffer * {@literal size > 2}. * * @return AVA object of the first AVA component in the Ldap DN string. */ public AVA parseAVA(PushbackReader in) throws IOException { return parseAVA(in, null); } /** * Like parseAVA(PushbackReader) with a DER encoding order given as * argument for Directory Strings. */ public AVA parseAVA(PushbackReader in, byte[] encodingOrder) throws IOException { int c; ObjectIdentifier oid; DerValue value; StringBuffer keywordBuf; StringBuffer valueBuf; ByteArrayOutputStream berStream; char hexChar1, hexChar2; CharArrayWriter hexCharsBuf; String endChars; /* First get the keyword indicating the attribute's type, * and map it to the appropriate OID. */ keywordBuf = new StringBuffer(); for (;;) { c = in.read(); if (c == '=') break; if (c == -1) { throw new IOException("Bad AVA format: Missing '='"); } keywordBuf.append((char) c); } oid = parseAVAKeyword(keywordBuf.toString()); /* Now parse the value. "#hex", a quoted string, or a string * terminated by "+", ",", ";", ">". Whitespace before or after * the value is stripped. */ for (c = in.read(); c == ' '; c = in.read()) continue; if (c == -1) throw new IOException("Bad AVA format: Missing attribute value"); if (c == '#') { /* * NOTE per LDAPv3 dn string ietf standard the value represented * by this form is a BER value. But we only support DER value here * which is only a form of BER. */ berStream = new ByteArrayOutputStream(); int b; for (;;) { hexChar1 = (char) (c = in.read()); if (c == -1 || octoEndChars.indexOf(c) > 0) // end of value break; hexChar2 = (char) (c = in.read()); if (hexDigits.indexOf(hexChar1) == -1 || hexDigits.indexOf(hexChar2) == -1) throw new IOException("Bad AVA value: bad hex value."); b = (Character.digit(hexChar1, 16) << 4) + Character.digit(hexChar2, 16); berStream.write(b); } if (berStream.size() == 0) throw new IOException("bad AVA format: invalid hex value"); value = parseAVAValue(berStream.toByteArray(), oid); while (c == ' ' && c != -1) c = in.read(); } else { valueBuf = new StringBuffer(); boolean quoted = false; if (c == '"') { quoted = true; endChars = quotedEndChars; if ((c = in.read()) == -1) throw new IOException("Bad AVA format: Missing attrValue"); } else { endChars = valueEndChars; } // QUOTATION * ( quotechar / pair ) QUOTATION // quotechar = any character except '\' or QUOTATION // pair = '\' ( special | '\' | QUOTATION | hexpair ) while (c != -1 && endChars.indexOf(c) == -1) { if (c == '\\') { if ((c = in.read()) == -1) throw new IOException("Bad AVA format: expecting " + "escaped char."); // expect escaping of special chars, space and CR. if (specialChars.indexOf((char) c) != -1 || c == '\n' || c == '\\' || c == '"' || c == ' ') { valueBuf.append((char) c); } else if (hexDigits.indexOf(c) != -1) { hexCharsBuf = new CharArrayWriter(); // handle sequence of '\' hexpair do { hexChar1 = (char) c; hexChar2 = (char) (c = in.read()); if (hexDigits.indexOf((char) c) == -1) throw new IOException("Bad AVA format: " + "invalid escaped hex pair"); hexCharsBuf.write(hexChar1); hexCharsBuf.write(hexChar2); // read ahead to next '\' hex-char if any. if ((c = in.read()) == -1) break; if (c != '\\') { in.unread(c); break; } if ((c = in.read()) == -1) throw new IOException("Bad AVA format: " + "expecting escaped char."); if (hexDigits.indexOf((char) c) == -1) { in.unread(c); in.unread('\\'); break; } } while (true); valueBuf.append( getStringFromHexpairs(hexCharsBuf.toCharArray())); } else { throw new IOException("Bad AVA format: " + "invalid escaping"); } } else valueBuf.append((char) c); c = in.read(); } value = parseAVAValue( valueBuf.toString().trim(), oid, encodingOrder); if (quoted) { // move to next non-white space do { c = in.read(); } while (c == ' '); if (c != -1 && valueEndChars.indexOf(c) == -1) throw new IOException( "Bad AVA format: separator expected at end of ava."); } } if (c != -1) in.unread(c); return new AVA(oid, value); } /** * Converts a AVA keyword from a Ldap DN string to an ObjectIdentifier * from the attribute map or, if this keyword is an OID not * in the attribute map, create a new ObjectIdentifier for the keyword * if acceptUnknownOids is true. * * @param avaKeyword AVA keyword from a Ldap DN string. * * @return a ObjectIdentifier object * @exception IOException if the keyword is an OID not in the attribute * map and acceptUnknownOids is false, or * if an error occurs during conversion. */ public ObjectIdentifier parseAVAKeyword(String avaKeyword) throws IOException { String keyword = avaKeyword.toUpperCase().trim(); String oid_str = null; ObjectIdentifier oid, new_oid; if (Character.digit(keyword.charAt(0), 10) != -1) { // value is an oid string of 1.2.3.4 oid_str = keyword; } else if (keyword.startsWith("oid.") || keyword.startsWith("OID.")) { // value is an oid string of oid.1.2.3.4 or OID.1.2... oid_str = keyword.substring(4); } if (oid_str != null) { // value is an oid string of 1.2.3.4 or oid.1.2.3.4 or OID.1.2... new_oid = new ObjectIdentifier(oid_str); oid = attrMap.getOid(new_oid); if (oid == null) { if (!acceptUnknownOids) throw new IOException("Unknown AVA OID."); oid = new_oid; } } else { oid = attrMap.getOid(keyword); if (oid == null) throw new IOException("Unknown AVA keyword '" + keyword + "'."); } return oid; } /** * Converts a AVA value from a Ldap dn string to a * DerValue according the attribute type. For example, a value for * CN, OU or O is expected to be a Directory String and will be converted * to a DerValue of ASN.1 type PrintableString, T61String or * UniversalString. A Directory String is a ASN.1 CHOICE of Printable, * T.61 or Universal string. * * @param avaValueString a attribute value from a Ldap DN string. * @param oid OID of the attribute. * * @return DerValue for the value. * * @exception IOException if an error occurs during conversion. * @see AVAValueConverter */ public DerValue parseAVAValue(String avaValueString, ObjectIdentifier oid) throws IOException { return parseAVAValue(avaValueString, oid, null); } /** * Like parseAVAValue(String) with a DER encoding order given as argument * for Directory Strings. */ public DerValue parseAVAValue( String avaValueString, ObjectIdentifier oid, byte[] encodingOrder) throws IOException { AVAValueConverter valueConverter = attrMap.getValueConverter(oid); if (valueConverter == null) { if (!acceptUnknownOids) { throw new IllegalArgumentException( "Unrecognized OID for AVA value conversion"); } else { valueConverter = new GenericValueConverter(); } } return valueConverter.getValue(avaValueString, encodingOrder); } /** * Converts a value in BER encoding, for example given in octothorpe form * in a Ldap v3 dn string, to a DerValue. Checks if the BER encoded value * is a legal value for the attribute. *

* NOTE: only DER encoded values are supported for the BER encoded value. * * @param berValue a value in BER encoding * @param oid ObjectIdentifier of the attribute. * * @return DerValue for the BER encoded value * @exception IOException if an error occurs during conversion. */ public DerValue parseAVAValue(byte[] berValue, ObjectIdentifier oid) throws IOException { AVAValueConverter valueConverter = attrMap.getValueConverter(oid); if (valueConverter == null && !acceptUnknownOids) { throw new IllegalArgumentException( "Unrecognized OID for AVA value conversion"); } else { valueConverter = new GenericValueConverter(); } return valueConverter.getValue(berValue); } // // public encoding methods. // /** * Converts a X500Name object to a Ldap v3 DN string (except in unicode). * * @param x500name a X500Name * * @return a Ldap v3 DN String (except in unicode). * * @exception IOException if an error is encountered during conversion. */ @Override public String encodeDN(X500Name x500name) throws IOException { RDN[] rdns = x500name.getNames(); // String fullname = null; StringBuffer fullname = new StringBuffer(); String s; int i; if (rdns.length == 0) return ""; i = rdns.length - 1; fullname.append(encodeRDN(rdns[i--])); while (i >= 0) { s = encodeRDN(rdns[i--]); fullname.append(","); fullname.append(s); } ; return fullname.toString(); } /** * Converts a RDN to a Ldap v3 DN string (except in unicode). * * @param rdn a RDN * * @return a LDAP v3 DN string (except in unicode). * * @exception IOException if an error is encountered during conversion. */ @Override public String encodeRDN(RDN rdn) throws IOException { AVA[] avas = rdn.getAssertion(); // String relname = null; StringBuffer relname = new StringBuffer(); String s; int i = 0; relname.append(encodeAVA(avas[i++])); while (i < avas.length) { s = encodeAVA(avas[i++]); relname.append("+"); relname.append(s); } ; return relname.toString(); } /** * Converts a AVA to a Ldap v3 DN String (except in unicode). * * @param ava an AVA * * @return a Ldap v3 DN string (except in unicode). * * @exception IOException If an error is encountered during exception. */ @Override public String encodeAVA(AVA ava) throws IOException { if (ava == null) { return ""; } ObjectIdentifier oid = ava.getOid(); DerValue value = ava.getValue(); String keyword, valueStr; // get attribute name keyword = encodeOID(oid); valueStr = encodeValue(value, oid); return keyword + "=" + valueStr; } /** * Converts an OID to a attribute keyword in a Ldap v3 DN string * - either a keyword if known or a string of "1.2.3.4" syntax. * * @param oid a ObjectIdentifier * * @return a keyword to use in a Ldap V3 DN string. * * @exception IOException if an error is encountered during conversion. */ public String encodeOID(ObjectIdentifier oid) throws IOException { String keyword = attrMap.getName(oid); if (keyword == null) { if (acceptUnknownOids) keyword = oid.toString(); else throw new IOException("Unknown OID"); } return keyword; } /** * Converts a value as a DerValue to a string in a Ldap V3 DN String. * If the value cannot be converted to a string it will be encoded in * octothorpe form. * * @param attrValue a value as a DerValue. * @param oid OID for the attribute. * @return a string for the value in a LDAP v3 DN String * @exception IOException if an error occurs during conversion. */ public String encodeValue(DerValue attrValue, ObjectIdentifier oid) throws IOException { /* * Construct the value with as little copying and garbage * production as practical. */ StringBuffer retval = new StringBuffer(30); int i; String temp = null; AVAValueConverter valueConverter; X500NameAttrMap lAttrMap = attrMap; if (attrValue.tag == DerValue.tag_UTF8String) { lAttrMap = X500NameAttrMap.getDirDefault(); } valueConverter = lAttrMap.getValueConverter(oid); if (valueConverter == null) { if (acceptUnknownOids) valueConverter = new GenericValueConverter(); else throw new IOException( "Unknown AVA type for encoding AVA value"); } try { temp = valueConverter.getAsString(attrValue); if (temp == null) { // convert to octothorpe form. byte data[] = attrValue.toByteArray(); retval.append('#'); for (i = 0; i < data.length; i++) { retval.append(hexDigits.charAt((data[i] >> 4) & 0x0f)); retval.append(hexDigits.charAt(data[i] & 0x0f)); } } else { retval.append(encodeString(temp)); } } catch (IOException e) { throw new IllegalArgumentException("malformed AVA DER Value"); } return retval.toString(); } /** * converts a raw value string to a string in Ldap V3 DN string format. * * @param valueStr a 'raw' value string. * @return a attribute value string in Ldap V3 DN string format. */ public String encodeString(String valueStr) { int i, j; int len; StringBuffer retval = new StringBuffer(); /* * generate string according to ldapv3 DN. escaping is used. * Strings generated this way are acceptable by rfc1779 * implementations. */ len = valueStr.length(); // get index of first space at the end of the string. for (j = len - 1; j >= 0 && valueStr.charAt(j) == ' '; j--) continue; // escape spaces at the beginning of the string. for (i = 0; i <= j && valueStr.charAt(i) == ' '; i++) { retval.append('\\'); retval.append(valueStr.charAt(i)); } // escape special characters in the middle of the string. for (; i <= j; i++) { if (valueStr.charAt(i) == '\\') { retval.append('\\'); retval.append(valueStr.charAt(i)); } else if (specialChars.indexOf(valueStr.charAt(i)) != -1) { retval.append('\\'); retval.append(valueStr.charAt(i)); } else if (valueStr.charAt(i) == '"') { retval.append('\\'); retval.append(valueStr.charAt(i)); } else retval.append(valueStr.charAt(i)); } // esacape spaces at the end. for (; i < valueStr.length(); i++) { retval.append('\\'); retval.append(' '); } return retval.toString(); } // // public get/set methods // /** * gets the X500NameAttrMap used by the converter. * * @return X500NameAttrMap used by this converter. */ public X500NameAttrMap getAttrMap() { return attrMap; } /** * returns true if the converter accepts unregistered attributes i.e. * OIDS not in the X500NameAttrMap. * * @return true if converter converts attributes not in the * X500NameAttrMap. */ public boolean getAcceptUnknownOids() { return acceptUnknownOids; } // // private and protected variables // protected X500NameAttrMap attrMap; protected boolean acceptUnknownOids; // // private and protected static variables & methods. // protected static final String specialChars = ",+=<>#;"; protected static final String valueEndChars = "+,;>"; protected static final String quotedEndChars = "\""; protected static final String octoEndChars = " " + valueEndChars; /* * Values that aren't printable strings are emitted as BER-encoded * hex data. */ protected static final String hexDigits = "0123456789ABCDEFabcdef"; /** * Parse a sequence of hex pairs, each pair a UTF8 byte to a java string. * For example, "4C75C48D" is "Luc", the last c with caron. */ protected static char[] getStringFromHexpairs(char[] hexPairs) throws UnsupportedEncodingException { try { byte[] buffer = new byte[hexPairs.length / 2]; for (int i = 0; i < buffer.length; i++) { buffer[i] = (byte) ((Character.digit(hexPairs[i * 2], 16) << 4) + Character.digit(hexPairs[i * 2 + 1], 16)); } Charset charset = Charset.forName("UTF-8"); CharsetDecoder decoder = charset.newDecoder(); CharBuffer charBuffer = decoder.decode(ByteBuffer.wrap(buffer)); return Arrays.copyOfRange(charBuffer.array(), charBuffer.arrayOffset(), charBuffer.arrayOffset() + charBuffer.limit()); } catch (UnsupportedCharsetException e) { throw new UnsupportedEncodingException( "No UTF8 byte to char converter to use for " + "parsing LDAP DN String"); } catch (CharacterCodingException e) { throw new IllegalArgumentException( "Invalid hex pair in LDAP DN String."); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/NSCCommentExtension.java000066400000000000000000000161301412550063600306730ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; import org.mozilla.jss.netscape.security.util.PrettyPrintFormat; /** * This class defines the NSCCommentExtension * * @author asondhi * @see Extension * @see CertAttrSet */ public class NSCCommentExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 4066287070285105375L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.CommentExtension"; /** * Attribute names. */ public static final String NAME = "NSCCommentExtension"; public static final String INFOS = "infos"; public static final ObjectIdentifier OID = new ObjectIdentifier("2.16.840.1.113730.1.13"); public String mComment = null; // Private data members private Vector mInfos; private transient PrettyPrintFormat pp = new PrettyPrintFormat(":"); // Encode this extension value private void encodeThis() throws IOException { try (DerOutputStream os = new DerOutputStream()) { os.putIA5String(mComment); // DerOutputStream tmp = new DerOutputStream(); // os.write(DerValue.tag_Sequence,tmp); extensionValue = os.toByteArray(); } } /** * Create a NSCCommentExtension with the Vector of CertificatePolicyInfo. */ public NSCCommentExtension(boolean critical, String comment) throws IOException { this.mComment = comment; this.extensionId = new ObjectIdentifier("2.16.840.1.113730.1.13"); this.critical = critical; encodeThis(); } /** * Create a default NSCCommentExtension. */ public NSCCommentExtension(boolean critical) { this.extensionId = new ObjectIdentifier("2.16.840.1.113730.1.13"); this.critical = critical; mInfos = new Vector(1, 1); } /** * Create the extension from the passed DER encoded value. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public NSCCommentExtension(Boolean critical, Object value) throws IOException { this.extensionId = new ObjectIdentifier("2.16.840.1.113730.1.13"); this.critical = critical.booleanValue(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); mComment = val.getIA5String(); } /** * Returns a printable representation of the policy extension. */ @Override public String toString() { if (mInfos == null) return ""; String s = super.toString() + "Netscape Comment [\n" + mInfos.toString() + "]\n"; return (s); } public String toPrint(int indent) { String s; s = "Comment :\n" + pp.indent(indent + 4) + ((mComment == null) ? "" : mComment.trim()) + "\n"; return (s); } /** * Write the extension to the OutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on encoding errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { extensionId = new ObjectIdentifier("2.16.840.1.113730.1.13"); critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } public String getComment() { return mComment; } /** * Set the attribute value. */ @Override @SuppressWarnings("unchecked") public void set(String name, Object obj) throws IOException { clearValue(); if (name.equalsIgnoreCase(INFOS)) { if (!(obj instanceof Vector)) { throw new IOException("Attribute value should be of" + " type Vector."); } mInfos = (Vector) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:NSCCommentExtension."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(INFOS)) { return (mInfos); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:NSCCommentExtension."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(INFOS)) { mInfos = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:NSCCommentExtension."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(INFOS); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/NameConstraintsExtension.java000066400000000000000000000270651412550063600320460ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.PrettyPrintFormat; /** * This class defines the Name Constraints Extension. *

* The name constraints extension provides permitted and excluded subtrees that place restrictions on names that may be * included within a certificate issued by a given CA. Restrictions may apply to the subject distinguished name or * subject alternative names. Any name matching a restriction in the excluded subtrees field is invalid regardless of * information appearing in the permitted subtrees. *

* The ASN.1 syntax for this is: * *

 * NameConstraints ::= SEQUENCE {
 *    permittedSubtrees [0]  GeneralSubtrees OPTIONAL,
 *    excludedSubtrees  [1]  GeneralSubtrees OPTIONAL
 * }
 * GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
 * GeneralSubtree ::== SEQUENCE {
 *    base                   GeneralName,
 *    minimum           [0]  BaseDistance DEFAULT 0,
 *    maximum           [1]  BaseDistance OPTIONAL }
 * BaseDistance ::== INTEGER (0..MAX)
 * 
* * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.10 * @see Extension * @see CertAttrSet */ public class NameConstraintsExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -3506940192931244539L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.NameConstraints"; /** * Attribute names. */ public static final String NAME = "NameConstraints"; public static final String PERMITTED_SUBTREES = "permitted_subtrees"; public static final String EXCLUDED_SUBTREES = "excluded_subtrees"; // Private data members private static final byte TAG_PERMITTED = 0; private static final byte TAG_EXCLUDED = 1; private GeneralSubtrees permitted; private GeneralSubtrees excluded; private transient PrettyPrintFormat pp = new PrettyPrintFormat(":"); // Encode this extension value. private void encodeThis() throws IOException { try (DerOutputStream seq = new DerOutputStream()) { DerOutputStream tagged = new DerOutputStream(); if ((permitted != null) && (permitted.getSubtrees().size() > 0)) { DerOutputStream tmp = new DerOutputStream(); permitted.encode(tmp); tagged.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, true, TAG_PERMITTED), tmp); } if ((excluded != null) && (excluded.getSubtrees().size() > 0)) { DerOutputStream tmp = new DerOutputStream(); excluded.encode(tmp); tagged.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, true, TAG_EXCLUDED), tmp); } if (permitted == null && excluded == null) { extensionValue = null; // no need to encode this extension } else { seq.write(DerValue.tag_Sequence, tagged); this.extensionValue = seq.toByteArray(); } } } /** * The default constructor for this class. Either parameter * can be set to null to indicate it is omitted but both * cannot be null. * * @param permitted the permitted GeneralSubtrees (null for optional). * @param excluded the excluded GeneralSubtrees (null for optional). */ public NameConstraintsExtension(GeneralSubtrees permitted, GeneralSubtrees excluded) throws IOException { init(false, permitted, excluded); } public NameConstraintsExtension(boolean critical, GeneralSubtrees permitted, GeneralSubtrees excluded) throws IOException { init(critical, permitted, excluded); } private void init(boolean critical, GeneralSubtrees permitted, GeneralSubtrees excluded) throws IOException { if (permitted == null && excluded == null) { throw new IOException("NameConstraints: Invalid arguments"); } this.permitted = permitted; this.excluded = excluded; this.extensionId = PKIXExtensions.NameConstraints_Id; this.critical = critical; encodeThis(); } /** * Create the extension from the passed DER encoded value. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public NameConstraintsExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.NameConstraints_Id; this.critical = critical.booleanValue(); if (!(value instanceof byte[])) throw new IOException("Illegal argument type"); int len = Array.getLength(value); byte[] extValue = new byte[len]; System.arraycopy(value, 0, extValue, 0, len); this.extensionValue = extValue; DerValue val = new DerValue(extValue); if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for" + " NameConstraintsExtension."); } // NB. this is always encoded with the IMPLICIT tag // The checks only make sense if we assume implicit tagging, // with explicit tagging the form is always constructed. while (val.data.available() != 0) { DerValue opt = val.data.getDerValue(); if (opt.isContextSpecific(TAG_PERMITTED) && opt.isConstructed()) { if (permitted != null) { throw new IOException("Duplicate permitted " + "GeneralSubtrees in NameConstraintsExtension."); } opt.resetTag(DerValue.tag_Sequence); permitted = new GeneralSubtrees(opt); } else if (opt.isContextSpecific(TAG_EXCLUDED) && opt.isConstructed()) { if (excluded != null) { throw new IOException("Duplicate excluded " + "GeneralSubtrees in NameConstraintsExtension."); } opt.resetTag(DerValue.tag_Sequence); excluded = new GeneralSubtrees(opt); } else throw new IOException("Invalid encoding of " + "NameConstraintsExtension."); } } /** * Return the printable string. */ @Override public String toString() { return (super.toString() + "NameConstraints: [" + ((permitted == null) ? "" : ("\n Permitted:" + permitted.toString())) + ((excluded == null) ? "" : ("\n Excluded:" + excluded.toString())) + " ]\n"); } public String toPrint(int indent) { return ("GeneralSubtrees: " + ((permitted == null) ? "" : ("\n" + pp.indent(indent + 2) + "Permitted:" + permitted.toPrint(indent + 4))) + ((excluded == null) ? "" : ("\n" + pp.indent(indent + 2) + "Excluded:" + excluded.toPrint(indent + 4))) + "\n"); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the OutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on encoding errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (this.extensionValue == null) { this.extensionId = PKIXExtensions.NameConstraints_Id; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { clearValue(); if (name.equalsIgnoreCase(PERMITTED_SUBTREES)) { if (!(obj instanceof GeneralSubtrees)) { throw new IOException("Attribute value should be" + " of type GeneralSubtrees."); } permitted = (GeneralSubtrees) obj; } else if (name.equalsIgnoreCase(EXCLUDED_SUBTREES)) { if (!(obj instanceof GeneralSubtrees)) { throw new IOException("Attribute value should be " + "of type GeneralSubtrees."); } excluded = (GeneralSubtrees) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:NameConstraintsExtension."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(PERMITTED_SUBTREES)) { return (permitted); } else if (name.equalsIgnoreCase(EXCLUDED_SUBTREES)) { return (excluded); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:NameConstraintsExtension."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(PERMITTED_SUBTREES)) { permitted = null; } else if (name.equalsIgnoreCase(EXCLUDED_SUBTREES)) { excluded = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:NameConstraintsExtension."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(PERMITTED_SUBTREES); elements.addElement(EXCLUDED_SUBTREES); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/NoticeReference.java000066400000000000000000000062171412550063600300750ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.Serializable; import java.util.Vector; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * Represent the NoticeReference. * * NoticeReference ::= SEQUENCE { * organization DisplayText, * noticeNumbers SEQUENCE OF INTEGER * } * * @author Thomas Kwan */ public class NoticeReference implements Serializable { private static final long serialVersionUID = 1986080941078808200L; private DisplayText mOrg = null; private int mNumbers[] = null; public NoticeReference(DisplayText org, int numbers[]) { mOrg = org; mNumbers = numbers; } public NoticeReference(DerValue val) throws IOException { if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for NoticeReference"); } mOrg = new DisplayText(val.data.getDerValue()); DerValue integers = val.data.getDerValue(); if (integers.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for NoticeReference (integers)"); } Vector num = new Vector(); while (integers.data.available() != 0) { DerValue i = integers.data.getDerValue(); BigInt bigI = i.getInteger(); num.addElement(bigI); } if (num.size() <= 0) return; mNumbers = new int[num.size()]; for (int i = 0; i < num.size(); i++) { mNumbers[i] = num.elementAt(i).toInt(); } } public DisplayText getOrganization() { return mOrg; } public int[] getNumbers() { return mNumbers; } /** * Write the NoticeReference to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException on errors. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); mOrg.encode(tmp); DerOutputStream iseq = new DerOutputStream(); for (int i = 0; i < mNumbers.length; i++) { iseq.putInteger(new BigInt(mNumbers[i])); } tmp.write(DerValue.tag_Sequence, iseq); out.write(DerValue.tag_Sequence, tmp); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/OIDMap.java000066400000000000000000000326421412550063600261070ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.security.cert.CertificateException; import java.util.Hashtable; import java.util.Iterator; import java.util.Properties; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** * This class defines the mapping from OID and name to classes and vice * versa. Used by CertificateExtensions and PKCS10 to get the java * classes associated with a particular OID/name. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.12 */ public class OIDMap { /** * Location for where the OID/Classes maps are stored on * the local system. */ public static final String EXTENSIONS_HOME = (System.getProperty("java.home") + File.separator + "lib" + File.separator + "security" + File.separator + "cert" + File.separator); /** * File names for where OIDs and Classes are registered * for V3 extensions. */ public static final String EXTENSIONS_OIDS = "x509extensions.oid"; public static final String EXTENSIONS_CLASSES = "x509extensions.classes"; // Make default names easier private static final String ROOT = X509CertImpl.NAME + "." + X509CertInfo.NAME + "." + X509CertInfo.EXTENSIONS; private static final String AUTH_KEY_IDENTIFIER = ROOT + "." + AuthorityKeyIdentifierExtension.NAME; private static final String SUB_KEY_IDENTIFIER = ROOT + "." + SubjectKeyIdentifierExtension.NAME; private static final String KEY_USAGE = ROOT + "." + KeyUsageExtension.NAME; private static final String PRIVATE_KEY_USAGE = ROOT + "." + PrivateKeyUsageExtension.NAME; private static final String POLICY_MAPPINGS = ROOT + "." + PolicyMappingsExtension.NAME; private static final String SUB_ALT_NAME = ROOT + "." + SubjectAlternativeNameExtension.NAME; private static final String ISSUER_ALT_NAME = ROOT + "." + IssuerAlternativeNameExtension.NAME; private static final String BASIC_CONSTRAINTS = ROOT + "." + BasicConstraintsExtension.NAME; private static final String NAME_CONSTRAINTS = ROOT + "." + NameConstraintsExtension.NAME; private static final String POLICY_CONSTRAINTS = ROOT + "." + PolicyConstraintsExtension.NAME; private static final String CERT_POLICIES = ROOT + "." + CertificatePoliciesExtension.NAME; private static final String SUBJ_DIR_ATTR = ROOT + "." + SubjectDirAttributesExtension.NAME; public static final String EXT_KEY_USAGE_NAME = "ExtendedKeyUsageExtension"; public static final String EXT_INHIBIT_ANY_POLICY_NAME = "InhibitAnyPolicyExtension"; private static final String EXT_KEY_USAGE = ROOT + "." + EXT_KEY_USAGE_NAME; private static final String CRL_NUMBER = ROOT + "." + CRLNumberExtension.NAME; private static final String CRL_REASON = ROOT + "." + CRLReasonExtension.NAME; private static final Hashtable oid2Name = new Hashtable(); private static final Hashtable name2OID = new Hashtable(); private static final Hashtable name2Class = new Hashtable(); // Initialize recognized extensions from EXTENSIONS_{OIDS/CLASSES} files static { loadNames(); loadClasses(); addClass(CRLDistributionPointsExtension.class); } // Load the default name to oid map (EXTENSIONS_OIDS) private static void loadNamesDefault(Properties props) { props.put(SUB_KEY_IDENTIFIER, "2.5.29.14"); props.put(KEY_USAGE, "2.5.29.15"); props.put(PRIVATE_KEY_USAGE, "2.5.29.16"); props.put(SUB_ALT_NAME, "2.5.29.17"); props.put(ISSUER_ALT_NAME, "2.5.29.18"); props.put(BASIC_CONSTRAINTS, "2.5.29.19"); props.put(CRL_NUMBER, "2.5.29.20"); props.put(CRL_REASON, "2.5.29.21"); props.put(NAME_CONSTRAINTS, "2.5.29.30"); props.put(POLICY_MAPPINGS, "2.5.29.33"); props.put(POLICY_CONSTRAINTS, "2.5.29.36"); props.put(CERT_POLICIES, "2.5.29.32"); props.put(AUTH_KEY_IDENTIFIER, "2.5.29.35"); props.put(SUBJ_DIR_ATTR, "2.5.29.9"); props.put(EXT_KEY_USAGE, "2.5.29.37"); } // Load the default name to class map (EXTENSIONS_CLASSES) private static void loadClassDefault(Properties props) { props.put(AUTH_KEY_IDENTIFIER, "org.mozilla.jss.netscape.security.x509.AuthorityKeyIdentifierExtension"); props.put(SUB_KEY_IDENTIFIER, "org.mozilla.jss.netscape.security.x509.SubjectKeyIdentifierExtension"); props.put(KEY_USAGE, "org.mozilla.jss.netscape.security.x509.KeyUsageExtension"); props.put(PRIVATE_KEY_USAGE, "org.mozilla.jss.netscape.security.x509.PrivateKeyUsageExtension"); props.put(POLICY_MAPPINGS, "org.mozilla.jss.netscape.security.x509.PolicyMappingsExtension"); props.put(SUB_ALT_NAME, "org.mozilla.jss.netscape.security.x509.SubjectAlternativeNameExtension"); props.put(ISSUER_ALT_NAME, "org.mozilla.jss.netscape.security.x509.IssuerAlternativeNameExtension"); props.put(BASIC_CONSTRAINTS, "org.mozilla.jss.netscape.security.x509.BasicConstraintsExtension"); props.put(NAME_CONSTRAINTS, "org.mozilla.jss.netscape.security.x509.NameConstraintsExtension"); props.put(POLICY_CONSTRAINTS, "org.mozilla.jss.netscape.security.x509.PolicyConstraintsExtension"); props.put(CERT_POLICIES, "org.mozilla.jss.netscape.security.x509.CertificatePoliciesExtension"); props.put(SUBJ_DIR_ATTR, "org.mozilla.jss.netscape.security.x509.SubjectDirAttributesExtension"); props.put(EXT_KEY_USAGE, "org.mozilla.jss.netscape.security.extensions.ExtendedKeyUsageExtension"); props.put(CRL_NUMBER, "org.mozilla.jss.netscape.security.x509.CRLNumberExtension"); props.put(CRL_REASON, "org.mozilla.jss.netscape.security.x509.CRLReasonExtension"); } // Return the file along with location private static File certificatePropFile(String fileName) { return (new File(EXTENSIONS_HOME + fileName)); } // Load the names to oid map private static void loadNames() { Properties props = new Properties(); File namesMap = certificatePropFile(EXTENSIONS_OIDS); if (!namesMap.exists()) { loadNamesDefault(props); } else { FileInputStream fis = null; try { fis = new FileInputStream(namesMap); props.load(fis); } catch (IOException e) { loadNamesDefault(props); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } Iterator names = props.stringPropertyNames().iterator(); while (names.hasNext()) { String name = names.next(); String oidName = props.getProperty(name); ObjectIdentifier oid = new ObjectIdentifier(oidName); name2OID.put(name, oid); oid2Name.put(oid, name); } } // Load the names to classes map private static void loadClasses() { Properties props = new Properties(); File classMap = certificatePropFile(EXTENSIONS_CLASSES); if (!classMap.exists()) { loadClassDefault(props); } else { FileInputStream fis = null; try { fis = new FileInputStream(classMap); props.load(fis); } catch (IOException e) { loadClassDefault(props); } finally { if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } Iterator names = props.stringPropertyNames().iterator(); while (names.hasNext()) { String name = names.next(); String className = props.getProperty(name); name2Class.put(name, className); } } /** * Add an extension to the OIDMap. * * Assumes existence of static OID and NAME fields with unique values. */ public static void addClass(Class clazz) { try { addAttribute(clazz.getName(), (String) clazz.getField("OID").get(null), (String) clazz.getField("NAME").get(null)); } catch (Throwable e) { System.out.println( "Error adding class " + clazz.getName() + " to OIDMap: " + e); } } /** * Add a name to lookup table. * * @param className the name of the fully qualified class implementing * the asn object. * @param oid the string representation of the object identifier for * the class. * @param name the name of the attribute. * @exception CertificateException on errors. */ public static void addAttribute(String className, String oid, String name) throws CertificateException { ObjectIdentifier objId = new ObjectIdentifier(oid); if (oid2Name.get(objId) != null) { throw new CertificateException("Object identifier already exists."); } if (name2OID.get(name) != null) { throw new CertificateException("Name already exists."); } if (name2Class.get(className) != null) { throw new CertificateException("Class already exists."); } oid2Name.put(objId, name); name2OID.put(name, objId); name2Class.put(name, className); } /** * Return user friendly name associated with the OID. * * @param oid the name of the object identifier to be returned. * @return the user friendly name or null if no name * is registered for this oid. */ public static String getName(ObjectIdentifier oid) { return oid2Name.get(oid); } /** * Return Object identifier for user friendly name. * * @param name the user friendly name. * @return the Object Identifier or null if no oid * is registered for this name. */ public static ObjectIdentifier getOID(String name) { return name2OID.get(name); } /** * Return the java class object associated with the user friendly name. * * @param name the user friendly name. * @exception CertificateException if class cannot be instantiated. */ public static Class getClass(String name) throws CertificateException { String className = name2Class.get(name); if (className == null) return null; try { Class extClass = Class.forName(className); return (extClass); } catch (Exception e) { throw new CertificateException("Error instantiating class for " + name + " " + e.toString()); } } /** * Return the java class object associated with the object identifier.. * * @param oid the name of the object identifier to be returned. * @exception CertificateException if class cannot be instatiated. */ public static Class getClass(ObjectIdentifier oid) throws CertificateException { String name = getName(oid); if (name == null) return null; String className = name2Class.get(name); if (className == null) return null; try { Class extClass = Class.forName(className); return (extClass); } catch (Exception e) { throw new CertificateException("Error instantiating class for " + name + " " + e.getMessage(), e); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/OIDName.java000066400000000000000000000051151412550063600262450ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** * This class implements the OIDName as required by the GeneralNames * ASN.1 object. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.3 * @see GeneralName * @see GeneralNames * @see GeneralNameInterface */ public class OIDName implements GeneralNameInterface { /** * */ private static final long serialVersionUID = 9198510631835117121L; private ObjectIdentifier oid; /** * Create the OIDName object from the passed encoded Der value. * * @param derValue the encoded DER OIDName. * @exception IOException on error. */ public OIDName(DerValue derValue) throws IOException { oid = derValue.getOID(); } /** * Create the OIDName object with the specified name. * * @param oid the OIDName. */ public OIDName(ObjectIdentifier oid) { this.oid = oid; } public OIDName(String oid) { this.oid = new ObjectIdentifier(oid); } /** * Return the type of the GeneralName. */ @Override public int getType() { return (GeneralNameInterface.NAME_OID); } /** * Encode the OID name into the DerOutputStream. * * @param out the DER stream to encode the OIDName to. * @exception IOException on encoding errors. */ @Override public void encode(DerOutputStream out) throws IOException { out.putOID(oid); } /** * Convert the name into user readable string. */ @Override public String toString() { return ("OIDName: " + oid.toString()); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/OtherName.java000066400000000000000000000146741412550063600267250ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** * This class implements the OtherName as required by the GeneralNames * ASN.1 object. * * OtherName ::= SEQUENCE { * type-id OBJECT IDENTIFIER, * value [0] EXPLICIT ANY DEFINED BY type-id * } * * @see GeneralName * @see GeneralNameInterface * @see GeneralNames * * @version 1.2 * * @author Amit Kapoor * @author Hemma Prafullchandra */ public class OtherName implements GeneralNameInterface { /** * */ private static final long serialVersionUID = -3533614377346132611L; private ObjectIdentifier mOID = null; private byte[] mData = null; /** * Create the IPAddressName object from the passed encoded Der value. * * @param derValue the encoded DER IPAddressName. * @exception IOException on error. */ public OtherName(DerValue derValue) throws IOException { decodeThis(derValue); } public OtherName(ObjectIdentifier oid, byte data[]) throws IOException { mOID = oid; DerOutputStream dos = new DerOutputStream(); try { dos.putDerValue(new DerValue(data)); } catch (IOException e) { } finally { dos.close(); } mData = dos.toByteArray(); } /** * Constructs a string-based other name. */ public OtherName(ObjectIdentifier oid, byte tag, String value) throws IOException { mOID = oid; DerOutputStream dos = new DerOutputStream(); try { if (tag == DerValue.tag_PrintableString) { dos.putPrintableString(value); } else if (tag == DerValue.tag_IA5String) { dos.putIA5String(value); } else if (tag == DerValue.tag_BMPString) { dos.putBMPString(value); } else if (tag == DerValue.tag_UTF8String) { dos.putUTF8String(value); } } catch (IOException e) { } finally { dos.close(); } mData = dos.toByteArray(); } public OtherName(ObjectIdentifier oid, String value) throws IOException { mOID = oid; DerOutputStream dos = new DerOutputStream(); try { dos.putPrintableString(value); } catch (IOException e) { } finally { dos.close(); } mData = dos.toByteArray(); } public OtherName(byte[] data) { try { decodeThis(new DerValue(data)); } catch (IOException e) { } } public ObjectIdentifier getOID() { return mOID; } /** * Return the type of the GeneralName. */ @Override public int getType() { return (GeneralNameInterface.NAME_ANY); } /** * Encode the IPAddress name into the DerOutputStream. * * @param out the DER stream to encode the IPAddressName to. * @exception IOException on encoding errors. */ @Override public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); //encoding the attributes tmp.putOID(mOID); DerOutputStream tmp1 = new DerOutputStream(); tmp1.write(mData); tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0x80), tmp1); out.write(DerValue.tag_SequenceOf, tmp); } public void decode(InputStream in) throws IOException { DerValue val = new DerValue(in); decodeThis(val); } // Decode this extension value private void decodeThis(DerValue derVal) throws IOException { // if (derVal.tag != DerValue.tag_Sequence) { // throw new IOException("Invalid encoding for other name"); // } // Decode all the Attributes mOID = derVal.data.getOID(); // skip tag DerValue tag = derVal.data.getDerValue(); // read data DerValue data = tag.data.getDerValue(); mData = data.toByteArray(); } public byte[] getValue() { return mData; } /** * Return a printable string of IPaddress */ @Override public String toString() { if (mData != null) { try { DerValue data = new DerValue(mData); if (data.tag == DerValue.tag_PrintableString) { return "OtherName: (PrintableString)" + mOID + "," + data.getPrintableString(); } else if (data.tag == DerValue.tag_IA5String) { return "OtherName: (IA5String)" + mOID + "," + data.getIA5String(); } else if (data.tag == DerValue.tag_BMPString) { return "OtherName: (BMPString)" + mOID + "," + data.getIA5String(); } else if (data.tag == DerValue.tag_UTF8String) { return "OtherName: (UTF8String)" + mOID + "," + data.getUTF8String(); } else { return "OtherName: (Any)" + mOID + "," + toStr(data.toByteArray()); } } catch (IOException e) { return "OtherName: (Any)" + mOID + "," + toStr(mData); } } else { return "OtherName: "; } } public String toStr(byte data[]) { StringBuffer b = new StringBuffer(); for (int i = 0; i < data.length; i++) { if ((data[i] & 0xff) < 16) { b.append("0"); } b.append(Integer.toString((data[i] & 0xff), 0x10)); } return b.toString(); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/PKIXExtensions.java000066400000000000000000000173401412550063600276670ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** * Lists all the object identifiers of the X509 extensions of the PKIX profile. * *

* Extensions are addiitonal attributes which can be inserted in a X509 v3 certificate. For example a * "Driving License Certificate" could have the driving license number as a extension. * *

* Extensions are represented as a sequence of the extension identifier (Object Identifier), a boolean flag stating * whether the extension is to be treated as being critical and the extension value itself (this is again a DER encoding * of the extension value). * * @see Extension * * @version 1.4 * * @author Amit Kapoor * @author Hemma Prafullchandra */ public class PKIXExtensions { // The object identifiers private static final int AuthorityKey_data[] = { 2, 5, 29, 35 }; private static final int SubjectKey_data[] = { 2, 5, 29, 14 }; private static final int KeyUsage_data[] = { 2, 5, 29, 15 }; private static final int PrivateKeyUsage_data[] = { 2, 5, 29, 16 }; private static final int CertificatePolicies_data[] = { 2, 5, 29, 32 }; private static final int PolicyMappings_data[] = { 2, 5, 29, 33 }; private static final int SubjectAlternativeName_data[] = { 2, 5, 29, 17 }; private static final int IssuerAlternativeName_data[] = { 2, 5, 29, 18 }; private static final int SubjectDirectoryAttributes_data[] = { 2, 5, 29, 9 }; private static final int BasicConstraints_data[] = { 2, 5, 29, 19 }; private static final int NameConstraints_data[] = { 2, 5, 29, 30 }; private static final int PolicyConstraints_data[] = { 2, 5, 29, 36 }; private static final int CRLDistributionPoints_data[] = { 2, 5, 29, 31 }; private static final int CRLNumber_data[] = { 2, 5, 29, 20 }; private static final int IssuingDistributionPoint_data[] = { 2, 5, 29, 28 }; private static final int DeltaCRLIndicator_data[] = { 2, 5, 29, 27 }; private static final int ReasonCode_data[] = { 2, 5, 29, 21 }; private static final int HoldInstructionCode_data[] = { 2, 5, 29, 23 }; private static final int InvalidityDate_data[] = { 2, 5, 29, 24 }; private static final int CertificateIssuer_data[] = { 2, 5, 29, 29 }; private static final int FreshestCRL_data[] = { 2, 5, 29, 46 }; /** * Identifies the particular public key used to sign the certificate. */ public static final ObjectIdentifier AuthorityKey_Id = new ObjectIdentifier(AuthorityKey_data); /** * Identifies the particular public key used in an application. */ public static final ObjectIdentifier SubjectKey_Id = new ObjectIdentifier(SubjectKey_data); /** * Defines the purpose of the key contained in the certificate. */ public static final ObjectIdentifier KeyUsage_Id = new ObjectIdentifier(KeyUsage_data); /** * Allows the certificate issuer to specify a different validity period * for the private key than the certificate. */ public static final ObjectIdentifier PrivateKeyUsage_Id = new ObjectIdentifier(PrivateKeyUsage_data); /** * Contains the sequence of policy information terms. */ public static final ObjectIdentifier CertificatePolicies_Id = new ObjectIdentifier(CertificatePolicies_data); /** * Lists pairs of objectidentifiers of policies considered equivalent by the * issuing CA to the subject CA. */ public static final ObjectIdentifier PolicyMappings_Id = new ObjectIdentifier(PolicyMappings_data); /** * Allows additional identities to be bound to the subject of the certificate. */ public static final ObjectIdentifier SubjectAlternativeName_Id = new ObjectIdentifier(SubjectAlternativeName_data); /** * Allows additional identities to be associated with the certificate issuer. */ public static final ObjectIdentifier IssuerAlternativeName_Id = new ObjectIdentifier(IssuerAlternativeName_data); /** * Identifies additional directory attributes. * This extension is always non-critical. */ public static final ObjectIdentifier SubjectDirectoryAttributes_Id = new ObjectIdentifier( SubjectDirectoryAttributes_data); /** * Identifies whether the subject of the certificate is a CA and how deep * a certification path may exist through that CA. */ public static final ObjectIdentifier BasicConstraints_Id = new ObjectIdentifier(BasicConstraints_data); /** * Provides for permitted and excluded subtrees that place restrictions * on names that may be included within a certificate issued by a given CA. */ public static final ObjectIdentifier NameConstraints_Id = new ObjectIdentifier(NameConstraints_data); /** * Used to either prohibit policy mapping or limit the set of policies * that can be in subsequent certificates. */ public static final ObjectIdentifier PolicyConstraints_Id = new ObjectIdentifier(PolicyConstraints_data); /** * Identifies how CRL information is obtained. */ public static final ObjectIdentifier CRLDistributionPoints_Id = new ObjectIdentifier(CRLDistributionPoints_data); /** * Conveys a monotonically increasing sequence number for each CRL * issued by a given CA. */ public static final ObjectIdentifier CRLNumber_Id = new ObjectIdentifier(CRLNumber_data); /** * Identifies the CRL distribution point for a particular CRL. */ public static final ObjectIdentifier IssuingDistributionPoint_Id = new ObjectIdentifier( IssuingDistributionPoint_data); /** * Identifies the delta CRL. */ public static final ObjectIdentifier DeltaCRLIndicator_Id = new ObjectIdentifier(DeltaCRLIndicator_data); /** * Identifies the reason for the certificate revocation. */ public static final ObjectIdentifier ReasonCode_Id = new ObjectIdentifier(ReasonCode_data); /** * This extension provides a registered instruction identifier indicating * the action to be taken, after encountering a certificate that has been * placed on hold. */ public static final ObjectIdentifier HoldInstructionCode_Id = new ObjectIdentifier(HoldInstructionCode_data); /** * Identifies the date on which it is known or suspected that the private * key was compromised or that the certificate otherwise became invalid. */ public static final ObjectIdentifier InvalidityDate_Id = new ObjectIdentifier(InvalidityDate_data); /** * Identifies the date on which it is known or suspected that the private * key was compromised or that the certificate otherwise became invalid. */ public static final ObjectIdentifier CertificateIssuer_Id = new ObjectIdentifier(CertificateIssuer_data); /** * Identifies how delta CRL information is obtained. */ public static final ObjectIdentifier FreshestCRL_Id = new ObjectIdentifier(FreshestCRL_data); } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/PolicyConstraint.java000066400000000000000000000114151412550063600303350ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class defines the PolicyConstraint ASN.1 object. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.4 */ public class PolicyConstraint { private static final byte TAG_SET = 0; private static final byte TAG_REQUIRE = 1; private static final byte TAG_INHIBIT = 2; private CertificatePolicySet set = null; private int require = -1; private int inhibit = -1; /** * The default constructor for this object * * @param set the CertificatePolicySet (null for optional). * @param require require explicit policy (-1 for optional). * @param inhibit inhibit policy mapping (-1 for optional). */ public PolicyConstraint(CertificatePolicySet set, int require, int inhibit) { this.set = set; this.require = require; this.inhibit = inhibit; } /** * Create the PolicyConstraint from the DerValue. * * @param val the DerValue of the PolicyConstraint. * @exception IOException on decoding errors. */ public PolicyConstraint(DerValue val) throws IOException { if (val.tag != DerValue.tag_Sequence) { throw new IOException("Sequence tag missing for PolicyConstraint."); } DerInputStream in = val.data; while (in != null && in.available() != 0) { DerValue next = in.getDerValue(); switch (next.tag & 0x1f) { case TAG_SET: this.set = new CertificatePolicySet(next.data); break; case TAG_REQUIRE: next = next.data.getDerValue(); this.require = (next.getInteger()).toInt(); break; case TAG_INHIBIT: next = next.data.getDerValue(); this.inhibit = (next.getInteger()).toInt(); break; default: throw new IOException("Invalid tag option for PolicyConstraint."); } } } /** * Return user readable form of the object. */ @Override public String toString() { String s = ((set != null) ? "PolicyConstraint: [\n" + " PolicySet:[" + set.toString() + "]\n" + " Require:" + require + "\n" + " Inhibit:" + inhibit + "\n" + "]\n" : "PolicyConstraint: [\n" + " PolicySet:[null]\n" + " Require:" + require + "\n" + " Inhibit:" + inhibit + "\n" + "]\n"); return (s); } /** * Encode the object to the output stream. * * @param out the DerOutputStream to encode the object to. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream tagged = new DerOutputStream(); if (set != null) { DerOutputStream tmp = new DerOutputStream(); set.encode(tmp); tagged.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, TAG_SET), tmp); } if (require != -1) { DerOutputStream tmp = new DerOutputStream(); tmp.putInteger(new BigInt(require)); tagged.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, TAG_REQUIRE), tmp); } if (inhibit != -1) { DerOutputStream tmp = new DerOutputStream(); tmp.putInteger(new BigInt(inhibit)); tagged.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, TAG_INHIBIT), tmp); } out.write(DerValue.tag_Sequence, tagged); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/PolicyConstraintsExtension.java000066400000000000000000000246251412550063600324240ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class defines the certificate extension which specifies the * Policy constraints. *

* The policy constraints extension can be used in certificates issued to CAs. The policy constraints extension * constrains path validation in two ways. It can be used to prohibit policy mapping or require that each certificate in * a path contain an acceptable policy identifier. *

* The ASN.1 syntax for this is (IMPLICIT tagging is defined in the module definition): * *

 * PolicyConstraints ::= SEQUENCE {
 *     requireExplicitPolicy [0] SkipCerts OPTIONAL,
 *     inhibitPolicyMapping  [1] SkipCerts OPTIONAL
 * }
 * SkipCerts ::= INTEGER (0..MAX)
 * 
* * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.9 * @see Extension * @see CertAttrSet */ public class PolicyConstraintsExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -3723759691127622370L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.PolicyConstraints"; /** * Attribute names. */ public static final String NAME = "PolicyConstraints"; public static final String REQUIRE = "require"; public static final String INHIBIT = "inhibit"; private static final byte TAG_REQUIRE = 0; private static final byte TAG_INHIBIT = 1; private int require = -1; private int inhibit = -1; // Encode this extension value. private void encodeThis() throws IOException { try (DerOutputStream seq = new DerOutputStream()) { DerOutputStream tagged = new DerOutputStream(); if (require != -1) { DerOutputStream tmp = new DerOutputStream(); tmp.putInteger(new BigInt(require)); tagged.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, false, TAG_REQUIRE), tmp); } if (inhibit != -1) { DerOutputStream tmp = new DerOutputStream(); tmp.putInteger(new BigInt(inhibit)); tagged.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, false, TAG_INHIBIT), tmp); } seq.write(DerValue.tag_Sequence, tagged); extensionValue = seq.toByteArray(); } } /** * Create a PolicyConstraintsExtension object with criticality and * both require explicit policy and inhibit policy mapping. * * @param crit whether this extension should be critical * @param require require explicit policy (-1 for optional). * @param inhibit inhibit policy mapping (-1 for optional). */ public PolicyConstraintsExtension(boolean crit, int require, int inhibit) throws IOException { init(crit, require, inhibit); } /** * Create a PolicyConstraintsExtension object with both * require explicit policy and inhibit policy mapping. * * @param require require explicit policy (-1 for optional). * @param inhibit inhibit policy mapping (-1 for optional). */ public PolicyConstraintsExtension(int require, int inhibit) throws IOException { init(false, require, inhibit); } private void init(boolean crit, int require, int inhibit) throws IOException { this.require = require; this.inhibit = inhibit; this.extensionId = PKIXExtensions.PolicyConstraints_Id; this.critical = crit; encodeThis(); } /** * Create the extension from its DER encoded value and criticality. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public PolicyConstraintsExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.PolicyConstraints_Id; this.critical = critical.booleanValue(); if (!(value instanceof byte[])) throw new IOException("Illegal argument type"); int len = Array.getLength(value); byte[] extValue = new byte[len]; System.arraycopy(value, 0, extValue, 0, len); this.extensionValue = extValue; DerValue val = new DerValue(extValue); if (val.tag != DerValue.tag_Sequence) { throw new IOException("Sequence tag missing for PolicyConstraint."); } DerInputStream in = val.data; while (in != null && in.available() != 0) { DerValue next = in.getDerValue(); if (next.isContextSpecific(TAG_REQUIRE) && !next.isConstructed()) { if (this.require != -1) throw new IOException("Duplicate requireExplicitPolicy" + "found in the PolicyConstraintsExtension"); next.resetTag(DerValue.tag_Integer); this.require = (next.getInteger()).toInt(); } else if (next.isContextSpecific(TAG_INHIBIT) && !next.isConstructed()) { if (this.inhibit != -1) throw new IOException("Duplicate inhibitPolicyMapping" + "found in the PolicyConstraintsExtension"); next.resetTag(DerValue.tag_Integer); this.inhibit = (next.getInteger()).toInt(); } else throw new IOException("Invalid encoding of PolicyConstraint"); } } /** * Return the extension as user readable string. */ @Override public String toString() { String s; s = super.toString() + "PolicyConstraints: [" + " Require: "; if (require == -1) s += "unspecified;"; else s += require + ";"; s += "\tInhibit: "; if (inhibit == -1) s += "unspecified"; else s += inhibit; s += " ]\n"; return s; } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { extensionId = PKIXExtensions.PolicyConstraints_Id; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { clearValue(); if (!(obj instanceof Integer)) { throw new IOException("Attribute value should be of type Integer."); } if (name.equalsIgnoreCase(REQUIRE)) { require = ((Integer) obj).intValue(); } else if (name.equalsIgnoreCase(INHIBIT)) { inhibit = ((Integer) obj).intValue(); } else { throw new IOException("Attribute name " + "[" + name + "]" + " not recognized by " + "CertAttrSet:PolicyConstraints."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(REQUIRE)) { return Integer.valueOf(require); } else if (name.equalsIgnoreCase(INHIBIT)) { return Integer.valueOf(inhibit); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:PolicyConstraints."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(REQUIRE)) { require = -1; } else if (name.equalsIgnoreCase(INHIBIT)) { inhibit = -1; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:PolicyConstraints."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(REQUIRE); elements.addElement(INHIBIT); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } /** * returns the requireExplicitMapping parameter. */ public int getRequireExplicitMapping() { return require; } /** * returns the inhibitPolicyMapping parameter. */ public int getInhibitPolicyMapping() { return inhibit; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/PolicyMappingsExtension.java000066400000000000000000000205671412550063600316740ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * Represent the Policy Mappings Extension. * * This extension, if present, identifies the certificate policies considered * identical between the issuing and the subject CA. *

* Extensions are addiitonal attributes which can be inserted in a X509 v3 certificate. For example a * "Driving License Certificate" could have the driving license number as a extension. * *

* Extensions are represented as a sequence of the extension identifier (Object Identifier), a boolean flag stating * whether the extension is to be treated as being critical and the extension value itself (this is again a DER encoding * of the extension value). * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.7 * @see Extension * @see CertAttrSet */ public class PolicyMappingsExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -4023336164621135851L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.PolicyMappings"; /** * Attribute names. */ public static final String NAME = "PolicyMappings"; public static final String MAP = "map"; // Private data members private Vector maps = null; // Encode this extension value private void encodeThis() throws IOException { try (DerOutputStream os = new DerOutputStream()) { DerOutputStream tmp = new DerOutputStream(); for (int i = 0; i < maps.size(); i++) { maps.elementAt(i).encode(tmp); } os.write(DerValue.tag_Sequence, tmp); extensionValue = os.toByteArray(); } } /** * Create a PolicyMappings with the Vector of CertificatePolicyMap. * * @param map the Vector of CertificatePolicyMap. */ public PolicyMappingsExtension(Vector map) throws IOException { init(false, map); } /** * Create a PolicyMappings with the Vector of CertificatePolicyMap. * * @param critical true if the extension is to be treated as critical. * @param map the Vector of CertificatePolicyMap. */ public PolicyMappingsExtension(boolean critical, Vector map) throws IOException { init(critical, map); } /** * init policy with criticality and map. */ private void init(boolean critical, Vector map) throws IOException { this.maps = map; this.extensionId = PKIXExtensions.PolicyMappings_Id; this.critical = critical; encodeThis(); } /** * Create a default PolicyMappingsExtension. */ public PolicyMappingsExtension() { extensionId = PKIXExtensions.PolicyMappings_Id; critical = false; maps = new Vector(1, 1); } /** * Create the extension from the passed DER encoded value. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public PolicyMappingsExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.PolicyMappings_Id; this.critical = critical.booleanValue(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for " + "PolicyMappingsExtension."); } maps = new Vector(1, 1); while (val.data.available() != 0) { DerValue seq = val.data.getDerValue(); CertificatePolicyMap map = new CertificatePolicyMap(seq); maps.addElement(map); } } /** * Returns a printable representation of the policy map. */ @Override public String toString() { if (maps == null) return ""; String s = super.toString() + "PolicyMappings [\n" + maps.toString() + "]\n"; return (s); } /** * Write the extension to the OutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on encoding errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { extensionId = PKIXExtensions.PolicyMappings_Id; critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Set the attribute value. */ @Override @SuppressWarnings("unchecked") public void set(String name, Object obj) throws IOException { clearValue(); if (name.equalsIgnoreCase(MAP)) { if (!(obj instanceof Vector)) { throw new IOException("Attribute value should be of" + " type Vector."); } maps = (Vector) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:PolicyMappingsExtension."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(MAP)) { return (maps); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:PolicyMappingsExtension."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(MAP)) { maps = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:PolicyMappingsExtension."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(MAP); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } /** * Returns an enumeration of the mappings in the extension. */ public Enumeration getMappings() { if (maps == null) return null; return maps.elements(); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/PolicyQualifierInfo.java000066400000000000000000000071711412550063600307520ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** * Represent the PolicyQualifierInfo. * * policyQualifierInfo ::= SEQUENCE { * policyQualifierId PolicyQualifierId * qualifier ANY DEFINED BY policyQualifierId * } * * @author Thomas Kwan */ public class PolicyQualifierInfo implements java.io.Serializable { /** * */ private static final long serialVersionUID = -2930016944517192379L; public static final int OID_CPS[] = { 1, 3, 6, 1, 5, 5, 7, 2, 1 }; public static final ObjectIdentifier QT_CPS = new ObjectIdentifier(OID_CPS); public static final int OID_UNOTICE[] = { 1, 3, 6, 1, 5, 5, 7, 2, 2 }; public static final ObjectIdentifier QT_UNOTICE = new ObjectIdentifier(OID_UNOTICE); private ObjectIdentifier mId = null; private Qualifier mQualifier = null; /** * Create a PolicyQualifierInfo * * @param id the ObjectIdentifier for the policy id. */ public PolicyQualifierInfo(ObjectIdentifier id, Qualifier qualifier) { mId = id; mQualifier = qualifier; } /** * Create the object from its Der encoded value. * * @param val the DER encoded value for the same. */ public PolicyQualifierInfo(DerValue val) throws IOException { if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for PolicyQualifierInfo."); } DerValue did = val.data.getDerValue(); mId = did.getOID(); if (val.data.available() != 0) { DerValue qualifier = val.data.getDerValue(); if (qualifier.tag == DerValue.tag_IA5String) { mQualifier = new CPSuri(qualifier); } else { mQualifier = new UserNotice(qualifier); } } } public ObjectIdentifier getId() { return mId; } /** * Returns object of type CPSuri or UserNotice. */ public Qualifier getQualifier() { return mQualifier; } /** * Returns a printable representation of the CertificatePolicyId. */ @Override public String toString() { String s = "PolicyQualifierInfo: ["; s = s + getId() + " " + getQualifier(); s = s + "]\n"; return (s); } /** * Write the PolicyQualifier to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException on errors. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); tmp.putOID(mId); mQualifier.encode(tmp); out.write(DerValue.tag_Sequence, tmp); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/PolicyQualifiers.java000066400000000000000000000061751412550063600303240ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * Represent the PolicyQualifiers. * * policyQualifiers ::= SEQUENCE SIZE (1..MAX) OF PolicyQualifierInfo * * @author Thomas Kwan */ public class PolicyQualifiers implements java.io.Serializable { /** * */ private static final long serialVersionUID = 6932694408774694516L; private Vector mInfo = new Vector(); /** * Create a PolicyQualifiers with the ObjectIdentifier. */ public PolicyQualifiers() { } /** * Create the object from its Der encoded value. * * @param val the DER encoded value for the same. */ public PolicyQualifiers(DerValue val) throws IOException { if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for " + "PolicyQualifiers."); } while (val.data.available() != 0) { DerValue pq = val.data.getDerValue(); PolicyQualifierInfo info = new PolicyQualifierInfo(pq); add(info); } } public void add(PolicyQualifierInfo info) { mInfo.addElement(info); } public int size() { return mInfo.size(); } public PolicyQualifierInfo getInfoAt(int i) { return mInfo.elementAt(i); } /** * Returns a printable representation of the CertificatePolicyId. */ @Override public String toString() { StringBuffer s = new StringBuffer("PolicyQualifiers: ["); for (int i = 0; i < mInfo.size(); i++) { PolicyQualifierInfo pq = mInfo.elementAt(i); s.append(pq.toString()); } s.append("]\n"); return s.toString(); } /** * Write the PolicyQualifiers to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException on errors. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); for (int i = 0; i < mInfo.size(); i++) { PolicyQualifierInfo pq = mInfo.elementAt(i); pq.encode(tmp); } out.write(DerValue.tag_Sequence, tmp); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/PrintableConverter.java000066400000000000000000000100411412550063600306330ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.CharsetEncoder; import org.mozilla.jss.netscape.security.util.ASN1CharStrConvMap; import org.mozilla.jss.netscape.security.util.DerValue; /** * A AVAValueConverter that converts a Printable String attribute to a DerValue * and vice versa. An example an attribute that is a printable string is "C". * * @see ASN1CharStrConvMap * @see AVAValueConverter * * @author Lily Hsiao, Slava Galperin at Netscape Communications, Inc. */ public class PrintableConverter implements AVAValueConverter { // public constructors. public PrintableConverter() { } /** * Converts a string with ASN.1 Printable characters to a DerValue. * * @param valueString a string with Printable characters. * * @return a DerValue. * * @exception IOException if a Printable encoder is not * available for the conversion. */ @Override public DerValue getValue(String valueString) throws IOException { return getValue(valueString, null); } @Override public DerValue getValue(String valueString, byte[] tags) throws IOException { try { CharsetEncoder encoder = ASN1CharStrConvMap.getDefault().getEncoder(DerValue.tag_PrintableString); if (encoder == null) throw new IOException("No encoder for printable"); CharBuffer charBuffer = CharBuffer.wrap(valueString.toCharArray()); ByteBuffer byteBuffer = encoder.encode(charBuffer); return new DerValue(DerValue.tag_PrintableString, byteBuffer.array(), byteBuffer.arrayOffset(), byteBuffer.limit()); } catch (CharacterCodingException e) { throw new IllegalArgumentException("Invalid Printable String AVA Value", e); } } /** * Converts a BER encoded value of PrintableString to a DER encoded value. * Checks if the BER encoded value is a PrintableString. * NOTE only DER encoded values are currently accepted on input. * * @param berStream A byte array of the BER encoded value. * * @return A DerValue. * * @exception IOException if the BER value cannot be converted to a * PrintableString DER value. */ @Override public DerValue getValue(byte[] berStream) throws IOException { DerValue value = new DerValue(berStream); if (value.tag != DerValue.tag_PrintableString) throw new IOException("Invalid Printable String AVA Value"); return value; } /** * Converts a DerValue of PrintableString to a java string with * PrintableString characters. * * @param avaValue a DerValue. * * @return a string with PrintableString characters. * * @exception IOException if the DerValue is not a PrintableString i.e. * The DerValue cannot be converted to a string * with PrintableString characters. */ @Override public String getAsString(DerValue avaValue) throws IOException { return avaValue.getPrintableString(); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/PrivateKeyUsageExtension.java000066400000000000000000000277671412550063600320170ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.security.cert.CertificateException; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateNotYetValidException; import java.security.cert.CertificateParsingException; import java.util.Date; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class defines the Private Key Usage Extension. * *

* The Private Key Usage Period extension allows the certificate issuer to specify a different validity period for the * private key than the certificate. This extension is intended for use with digital signature keys. This extension * consists of two optional components notBefore and notAfter. The private key associated with the certificate should * not be used to sign objects before or after the times specified by the two components, respectively. * *

 * PrivateKeyUsagePeriod ::= SEQUENCE {
 *     notBefore  [0]  GeneralizedTime OPTIONAL,
 *     notAfter   [1]  GeneralizedTime OPTIONAL }
 * 
* * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.12 * @see Extension * @see CertAttrSet */ public class PrivateKeyUsageExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -7623695233957629936L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.PrivateKeyUsage"; /** * Sub attributes name for this CertAttrSet. */ public static final String NAME = "PrivateKeyUsage"; public static final String NOT_BEFORE = "not_before"; public static final String NOT_AFTER = "not_after"; // Private data members private static final byte TAG_BEFORE = 0; private static final byte TAG_AFTER = 1; private Date notBefore; private Date notAfter; // Encode this extension value. private void encodeThis() throws IOException { try (DerOutputStream seq = new DerOutputStream()) { DerOutputStream tagged = new DerOutputStream(); if (notBefore != null) { DerOutputStream tmp = new DerOutputStream(); tmp.putGeneralizedTime(notBefore); tagged.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, false, TAG_BEFORE), tmp); } if (notAfter != null) { DerOutputStream tmp = new DerOutputStream(); tmp.putGeneralizedTime(notAfter); tagged.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT, false, TAG_AFTER), tmp); } seq.write(DerValue.tag_Sequence, tagged); extensionValue = seq.toByteArray(); } } /** * The default constructor for PrivateKeyUsageExtension. * * @param notBefore the date/time before which the private key * should not be used. * @param notAfter the date/time after which the private key * should not be used. */ public PrivateKeyUsageExtension(Date notBefore, Date notAfter) throws IOException { this.notBefore = notBefore; this.notAfter = notAfter; this.extensionId = PKIXExtensions.PrivateKeyUsage_Id; this.critical = false; encodeThis(); } /** * Create the extension from the passed DER encoded value. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * * @exception CertificateException on certificate parsing errors. * @exception IOException on error. */ public PrivateKeyUsageExtension(Boolean critical, Object value) throws CertificateException, IOException { this.extensionId = PKIXExtensions.PrivateKeyUsage_Id; this.critical = critical.booleanValue(); if (!(value instanceof byte[])) throw new CertificateException("Illegal argument type"); int len = Array.getLength(value); byte[] extValue = new byte[len]; System.arraycopy(value, 0, extValue, 0, len); this.extensionValue = extValue; DerInputStream str = new DerInputStream(extValue); DerValue[] seq = str.getSequence(2); // NB. this is always encoded with the IMPLICIT tag // The checks only make sense if we assume implicit tagging, // with explicit tagging the form is always constructed. for (int i = 0; i < seq.length; i++) { DerValue opt = seq[i]; if (opt.isContextSpecific(TAG_BEFORE) && !opt.isConstructed()) { if (notBefore != null) { throw new CertificateParsingException( "Duplicate notBefore in PrivateKeyUsage."); } opt.resetTag(DerValue.tag_GeneralizedTime); str = new DerInputStream(opt.toByteArray()); notBefore = str.getGeneralizedTime(); } else if (opt.isContextSpecific(TAG_AFTER) && !opt.isConstructed()) { if (notAfter != null) { throw new CertificateParsingException( "Duplicate notAfter in PrivateKeyUsage."); } opt.resetTag(DerValue.tag_GeneralizedTime); str = new DerInputStream(opt.toByteArray()); notAfter = str.getGeneralizedTime(); } else throw new IOException("Invalid encoding of " + "PrivateKeyUsageExtension"); } } /** * Return the printable string. */ @Override public String toString() { return (super.toString() + "PrivateKeyUsage: [From: " + ((notBefore == null) ? "" : notBefore.toString()) + ", To: " + ((notAfter == null) ? "" : notAfter.toString()) + "]\n"); } /** * Return notBefore date */ public Date getNotBefore() { return (notBefore); } /** * Return notAfter date */ public Date getNotAfter() { return (notAfter); } /** * Verify that that the current time is within the validity period. * * @exception CertificateExpiredException if the certificate has expired. * @exception CertificateNotYetValidException if the certificate is not * yet valid. */ public void valid() throws CertificateNotYetValidException, CertificateExpiredException { Date now = new Date(); valid(now); } /** * Verify that that the passed time is within the validity period. * * @exception CertificateExpiredException if the certificate has expired * with respect to the Date supplied. * @exception CertificateNotYetValidException if the certificate is not * yet valid with respect to the Date supplied. * */ public void valid(Date now) throws CertificateNotYetValidException, CertificateExpiredException { /* * we use the internal Dates rather than the passed in Date * because someone could override the Date methods after() * and before() to do something entirely different. */ if (notBefore.after(now)) { throw new CertificateNotYetValidException("NotBefore: " + notBefore.toString()); } if (notAfter.before(now)) { throw new CertificateExpiredException("NotAfter: " + notAfter.toString()); } } /** * Write the extension to the OutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on encoding errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { extensionId = PKIXExtensions.PrivateKeyUsage_Id; critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception CertificateException on decoding errors. */ @Override public void decode(InputStream in) throws CertificateException { throw new CertificateException("Method not to be called directly."); } /** * Set the attribute value. * * @exception CertificateException on attribute handling errors. */ @Override public void set(String name, Object obj) throws CertificateException { clearValue(); if (!(obj instanceof Date)) { throw new CertificateException("Attribute must be of type Date."); } if (name.equalsIgnoreCase(NOT_BEFORE)) { notBefore = (Date) obj; } else if (name.equalsIgnoreCase(NOT_AFTER)) { notAfter = (Date) obj; } else { throw new CertificateException("Attribute name not recognized by" + " CertAttrSet:PrivateKeyUsage."); } } /** * Get the attribute value. * * @exception CertificateException on attribute handling errors. */ @Override public Object get(String name) throws CertificateException { if (name.equalsIgnoreCase(NOT_BEFORE)) { return (new Date(notBefore.getTime())); } else if (name.equalsIgnoreCase(NOT_AFTER)) { return (new Date(notAfter.getTime())); } else { throw new CertificateException("Attribute name not recognized by" + " CertAttrSet:PrivateKeyUsage."); } } /** * Delete the attribute value. * * @exception CertificateException on attribute handling errors. */ @Override public void delete(String name) throws CertificateException { if (name.equalsIgnoreCase(NOT_BEFORE)) { notBefore = null; } else if (name.equalsIgnoreCase(NOT_AFTER)) { notAfter = null; } else { throw new CertificateException("Attribute name not recognized by" + " CertAttrSet:PrivateKeyUsage."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(NOT_BEFORE); elements.addElement(NOT_AFTER); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/Qualifier.java000066400000000000000000000033221412550063600267500ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * Represent the Qualifier. * * Qualifier ::= CHOICE { * cPRuri CPSuri, * userNotice UserNotice * } * * @author Thomas Kwan */ public class Qualifier implements java.io.Serializable { /** * */ private static final long serialVersionUID = 2214531407387992974L; /** * Create a PolicyQualifierInfo */ public Qualifier() { } public Qualifier(DerValue val) throws IOException { // needs to override this } /** * Write the PolicyQualifier to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException on errors. */ public void encode(DerOutputStream out) throws IOException { // needs to override this } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/RDN.java000066400000000000000000000212001412550063600254450ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.util.Arrays; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** * RDNs are a set of {attribute = value} assertions. Some of those * attributes are "distinguished" (unique w/in context). Order is * never relevant. * * Some X.500 names include only a single distinguished attribute * per RDN. This style is currently common. * * Note that DER-encoded RDNs sort AVAs by assertion OID ... so that * when we parse this data we don't have to worry about canonicalizing * it, but we'll need to sort them when we expose the RDN class more. * * @see X500Name * @see AVA * @see LdapDNStrConverter */ public class RDN { // public constructors /** * Constructs a RDN from a Ldap DN String with one RDN component * using the global default LdapDNStrConverter. * * @see LdapDNStrConverter * @param rdnString a Ldap DN string with one RDN component, e.g. as * defined in RFC1779. * @exception IOException if error occurs while parsing the string. */ public RDN(String rdnString) throws IOException { RDN rdn = LdapDNStrConverter.getDefault().parseRDN(rdnString); assertion = rdn.getAssertion(); } /** * Like RDN(String) with a DER encoding order given as argument for * Directory Strings. */ public RDN(String rdnString, byte[] tags) throws IOException { RDN rdn = LdapDNStrConverter.getDefault().parseRDN(rdnString, tags); assertion = rdn.getAssertion(); } /** * Constructs a RDN from a Ldap DN string with one RDN component * using the specified Ldap DN Str converter. * For example, RFC1779StrConverter can be passed to parse a Ldap * DN string in RFC1779 format. * * @see LdapDNStrConverter * @param rdnString Ldap DN string. * @param ldapDNStrConverter a LdapDNStrConverter. */ public RDN(String rdnString, LdapDNStrConverter ldapDNStrConverter) throws IOException { RDN rdn = ldapDNStrConverter.parseRDN(rdnString); assertion = rdn.getAssertion(); } /** * Constructs a RDN from a DerValue. * * @param set Der value of a set of AVAs. */ public RDN(DerValue set) throws IOException { if (set.tag != DerValue.tag_Set) throw new CertParseError("X500 RDN"); int j_max = 50; // XXX j_max = f(data)!! int j; int i; AVA[] avas = new AVA[j_max]; // create a temporary array big enough for a huge set of AVA's for (j = 0; j < j_max; j++) { avas[j] = new AVA(set.data); if (set.data.available() == 0) break; } // copy the elements into it if (j >= j_max - 1) { assertion = new AVA[j + 1]; } else { assertion = new AVA[j + 1]; for (i = 0; i < (j + 1); i++) { assertion[i] = avas[i]; } } /* if (set.data.available () != 0) // throw new CertParseError ("X500 RDN 2"); System.out.println (" ... RDN parse, ignored bytes = " + set.data.available ()); */ } /** * Constructs a RDN from a Der Input Stream. * * @param in a Der Input Stream. */ public RDN(DerInputStream in) throws IOException { /* an RDN is a SET of avas */ DerValue avaset[] = in.getSet(1); int i; assertion = new AVA[avaset.length]; for (i = 0; i < assertion.length; i++) assertion[i] = new AVA(avaset[i].data); } /** * Constructs a RDN from an array of AVA. * * @param avas a AVA Array. */ public RDN(AVA avas[]) { assertion = avas.clone(); } /** * convenience method. */ public RDN(Vector avaVector) { int size = avaVector.size(); assertion = new AVA[size]; for (int i = 0; i < size; i++) { assertion[i] = avaVector.elementAt(i); } } /** * returns an array of AVA in the RDN. * * @return array of AVA in this RDN. */ public AVA[] getAssertion() { return assertion.clone(); } /** * returns the number of AVAs in the RDN. * * @return number of AVAs in this RDN. */ public int getAssertionLength() { return assertion.length; } private AVA assertion[]; private class AVAEnumerator implements Enumeration { private int index; public AVAEnumerator() { index = 0; } @Override public boolean hasMoreElements() { return (index < assertion.length); } @Override public AVA nextElement() { if (index >= assertion.length) return null; return assertion[index++]; } } // other public methods. @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + Arrays.hashCode(assertion); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; RDN other = (RDN) obj; if (!Arrays.equals(assertion, other.assertion)) return false; return true; } DerValue findAttribute(ObjectIdentifier oid) { int i; for (i = 0; i < assertion.length; i++) if (assertion[i].oid.equals(oid)) return assertion[i].value; return null; } /** * Encodes this RDN to a Der output stream. * * @param out the Der Output Stream. */ public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); int i; for (i = 0; i < assertion.length; i++) assertion[i].encode(tmp); out.write(DerValue.tag_Set, tmp); } /** * returns an enumeration of AVAs that make up this RDN. * * @return an enumeration of AVAs that make up this RDN. */ public Enumeration getAVAs() { return new AVAEnumerator(); } /** * Returns a Ldap DN string with one RDN component using the * global default LdapDNStrConverter. * * @see LdapDNStrConverter * @return the Ldap DN String of this RDN. * @exception IOException if an error occurs during the conversion. */ public String toLdapDNString() throws IOException { return LdapDNStrConverter.getDefault().encodeRDN(this); } /** * Returns a Ldap DN String with this RDN component using the specified * LdapDNStrConverter. * * @see LdapDNStrConverter * @param ldapDNStrConverter a LdapDNStrConverter. * @return a Ldap DN String. * @exception IOException if an error occurs in the conversion. */ public String toLdapDNString(LdapDNStrConverter ldapDNStrConverter) throws IOException { return ldapDNStrConverter.encodeRDN(this); } /** * Returns a Ldap DN string with this RDN component using the global * default LdapDNStrConverter. * * @see LdapDNStrConverter * @return the Ldap DN String with this RDN component, null if an error * occurs in the conversion. */ @Override public String toString() { String s; try { s = toLdapDNString(); } catch (IOException e) { return null; } return s; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/RFC1779StrConverter.java000066400000000000000000000065421412550063600303610ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** * Converts a RFC 1779 string to a X500Name, RDN or AVA object and vice versa. * * @see LdapDNStrConverter * @see LdapV3DNStrConverter * * @author Lily Hsiao, Slava Galperin at Netscape Communications, Inc. */ public class RFC1779StrConverter extends LdapV3DNStrConverter { // // Constructors. // /** * Constructs a RFC1779StrConverter using the global default * X500NameAttrMap and accepts OIDs not listed in the attribute map. */ public RFC1779StrConverter() { super(); } /** * Constructs a RFC1779StrConverter using the specified X500NameAttrMap * and boolean for whether to accept OIDs not in the X500NameAttrMap. * * @param attributeMap A X500NameAttrMap to use for this converter. * @param doAcceptUnknownOids Accept unregistered attributes, i.e. OIDs * not in the map). */ public RFC1779StrConverter(X500NameAttrMap attributeMap, boolean doAcceptUnknownOids) { super(attributeMap, doAcceptUnknownOids); } // // overriding methods. // /** * Converts a OID to a attribute keyword in a Ldap DN string or * to a "OID.1.2.3.4" string syntax as defined in RFC1779. * * @param oid an ObjectIdentifier. * * @return a attribute keyword or "OID.1.2.3.4" string. * * @exception IOException if an error occurs during the conversion. */ @Override public String encodeOID(ObjectIdentifier oid) throws IOException { String keyword = attrMap.getName(oid); if (keyword == null) if (!acceptUnknownOids) throw new IllegalArgumentException("Unrecognized OID"); else keyword = "OID" + "." + oid.toString(); return keyword; } /** * Converts a attribute value as a DerValue to a string in a * RFC1779 Ldap DN string. * * @param attrValue an attribute value. * @param oid ObjectIdentifier for the attribute. * @return a string in RFC1779 syntax. * @exception IOException if an error occurs during the conversion. */ @Override public String encodeValue(DerValue attrValue, ObjectIdentifier oid) throws IOException { String s = super.encodeValue(attrValue, oid); if (s.indexOf('\n') != -1) return "\"" + s + "\""; else return s; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/RFC822Name.java000066400000000000000000000047211412550063600265020ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class implements the RFC822Name as required by the GeneralNames * ASN.1 object. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.3 * @see GeneralName * @see GeneralNames * @see GeneralNameInterface */ public class RFC822Name implements GeneralNameInterface { /** * */ private static final long serialVersionUID = -1453025303548809007L; private String name; /** * Create the RFC822Name object from the passed encoded Der value. * * @param derValue the encoded DER RFC822Name. * @exception IOException on error. */ public RFC822Name(DerValue derValue) throws IOException { name = derValue.getIA5String(); } /** * Create the RFC822Name object with the specified name. * * @param name the RFC822Name. */ public RFC822Name(String name) { this.name = name; } /** * Return the type of the GeneralName. */ @Override public int getType() { return (GeneralNameInterface.NAME_RFC822); } /** * Encode the RFC822 name into the DerOutputStream. * * @param out the DER stream to encode the RFC822Name to. * @exception IOException on encoding errors. */ @Override public void encode(DerOutputStream out) throws IOException { out.putIA5String(name); } /** * Convert the name into user readable string. */ @Override public String toString() { return ("RFC822Name: " + name); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/ReasonFlags.java000066400000000000000000000226031412550063600272360ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.BitArray; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * Represent the CRL Reason Flags. * *

* This extension, if present, defines the identifies the reason for the certificate revocation. * * @author Hemma Prafullchandra * @version 1.3 * @see Extension * @see CertAttrSet */ public class ReasonFlags { /** * Reasons */ public static final String UNUSED = "unused"; public static final String KEY_COMPROMISE = "key_compromise"; public static final String CA_COMPROMISE = "ca_compromise"; public static final String AFFLIATION_CHANGED = "affliation_changed"; public static final String SUPERSEDED = "superseded"; public static final String CESSATION_OF_OPERATION = "cessation_of_operation"; public static final String CERTIFICATION_HOLD = "certification_hold"; public static final String PRIVILEGE_WITHDRAWN = "privilege_withdrawn"; public static final String AA_COMPROMISE = "aa_compromise"; // Private data members private boolean[] bitString; /** * Check if bit is set. * * @param position the position in the bit string to check. */ private boolean isSet(int position) { return bitString[position]; } /** * Set the bit at the specified position. */ private void set(int position, boolean val) { // enlarge bitString if necessary if (position >= bitString.length) { boolean[] tmp = new boolean[position + 1]; System.arraycopy(bitString, 0, tmp, 0, bitString.length); bitString = tmp; } bitString[position] = val; } /** * Create a ReasonFlags with the passed bit settings. * * @param reasons the bits to be set for the ReasonFlags. */ public ReasonFlags(byte[] reasons) { bitString = new BitArray(reasons.length * 8, reasons).toBooleanArray(); } /** * Create a ReasonFlags with the passed bit settings. * * @param reasons the bits to be set for the ReasonFlags. */ public ReasonFlags(boolean[] reasons) { this.bitString = reasons; } /** * Create a ReasonFlags with the passed bit settings. * * @param reasons the bits to be set for the ReasonFlags. */ public ReasonFlags(BitArray reasons) { this.bitString = reasons.toBooleanArray(); } /** * Create the object from the passed DER encoded value. * * @param in the DerInputStream to read the ReasonFlags from. * @exception IOException on decoding errors. */ public ReasonFlags(DerInputStream in) throws IOException { DerValue derVal = in.getDerValue(); this.bitString = derVal.getUnalignedBitString(true).toBooleanArray(); } /** * Create the object from the passed DER encoded value. * * @param derVal the DerValue decoded from the stream. * @exception IOException on decoding errors. */ public ReasonFlags(DerValue derVal) throws IOException { this.bitString = derVal.getUnalignedBitString(true).toBooleanArray(); } /** * Set the attribute value. */ public void set(String name, Object obj) throws IOException { if (!(obj instanceof Boolean)) { throw new IOException("Attribute must be of type Boolean."); } boolean val = ((Boolean) obj).booleanValue(); if (name.equalsIgnoreCase(UNUSED)) { set(0, val); } else if (name.equalsIgnoreCase(KEY_COMPROMISE)) { set(1, val); } else if (name.equalsIgnoreCase(CA_COMPROMISE)) { set(2, val); } else if (name.equalsIgnoreCase(AFFLIATION_CHANGED)) { set(3, val); } else if (name.equalsIgnoreCase(SUPERSEDED)) { set(4, val); } else if (name.equalsIgnoreCase(CESSATION_OF_OPERATION)) { set(5, val); } else if (name.equalsIgnoreCase(CERTIFICATION_HOLD)) { set(6, val); } else if (name.equalsIgnoreCase(PRIVILEGE_WITHDRAWN)) { set(7, val); } else if (name.equalsIgnoreCase(AA_COMPROMISE)) { set(8, val); } else { throw new IOException("Name not recognized by ReasonFlags"); } } /** * Get the attribute value. */ public Object get(String name) throws IOException { if (name.equalsIgnoreCase(UNUSED)) { return Boolean.valueOf(isSet(0)); } else if (name.equalsIgnoreCase(KEY_COMPROMISE)) { return Boolean.valueOf(isSet(1)); } else if (name.equalsIgnoreCase(CA_COMPROMISE)) { return Boolean.valueOf(isSet(2)); } else if (name.equalsIgnoreCase(AFFLIATION_CHANGED)) { return Boolean.valueOf(isSet(3)); } else if (name.equalsIgnoreCase(SUPERSEDED)) { return Boolean.valueOf(isSet(4)); } else if (name.equalsIgnoreCase(CESSATION_OF_OPERATION)) { return Boolean.valueOf(isSet(5)); } else if (name.equalsIgnoreCase(CERTIFICATION_HOLD)) { return Boolean.valueOf(isSet(6)); } else if (name.equalsIgnoreCase(PRIVILEGE_WITHDRAWN)) { return Boolean.valueOf(isSet(7)); } else if (name.equalsIgnoreCase(AA_COMPROMISE)) { return Boolean.valueOf(isSet(8)); } else { throw new IOException("Name not recognized by ReasonFlags"); } } /** * Delete the attribute value. */ public void delete(String name) throws IOException { if (name.equalsIgnoreCase(UNUSED)) { set(0, false); } else if (name.equalsIgnoreCase(KEY_COMPROMISE)) { set(1, false); } else if (name.equalsIgnoreCase(CA_COMPROMISE)) { set(2, false); } else if (name.equalsIgnoreCase(AFFLIATION_CHANGED)) { set(3, false); } else if (name.equalsIgnoreCase(SUPERSEDED)) { set(4, false); } else if (name.equalsIgnoreCase(CESSATION_OF_OPERATION)) { set(5, false); } else if (name.equalsIgnoreCase(CERTIFICATION_HOLD)) { set(6, false); } else if (name.equalsIgnoreCase(PRIVILEGE_WITHDRAWN)) { set(7, false); } else if (name.equalsIgnoreCase(AA_COMPROMISE)) { set(8, false); } else { throw new IOException("Name not recognized by ReasonFlags"); } } /** * Returns a printable representation of the ReasonFlags. */ @Override public String toString() { String s = super.toString() + "Reason Flags [\n"; try { if (isSet(0)) { s += " Unused\n"; } if (isSet(1)) { s += " Key Compromise\n"; } if (isSet(2)) { s += " CA_Compromise\n"; } if (isSet(3)) { s += " Affiliation_Changed\n"; } if (isSet(4)) { s += " Superseded\n"; } if (isSet(5)) { s += " Cessation Of Operation\n"; } if (isSet(6)) { s += " Certificate Hold\n"; } if (isSet(7)) { s += " Privilege Withdrawn\n"; } if (isSet(8)) { s += " AA Compromise\n"; } } catch (ArrayIndexOutOfBoundsException ex) { } s += "]\n"; return (s); } /** * Write the extension to the DerOutputStream. * * @param out the DerOutputStream to write the extension to. * @exception IOException on encoding errors. */ public void encode(DerOutputStream out) throws IOException { out.putUnalignedBitString(new BitArray(this.bitString)); } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getElements() { Vector elements = new Vector(); elements.addElement(UNUSED); elements.addElement(KEY_COMPROMISE); elements.addElement(CA_COMPROMISE); elements.addElement(AFFLIATION_CHANGED); elements.addElement(SUPERSEDED); elements.addElement(CESSATION_OF_OPERATION); elements.addElement(CERTIFICATION_HOLD); elements.addElement(PRIVILEGE_WITHDRAWN); elements.addElement(AA_COMPROMISE); return (elements.elements()); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/RevocationReason.java000066400000000000000000000106411412550063600303120ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.Map; /** * Represent the enumerated type used in CRLReason Extension of CRL entry. * * * @author galperin * @version $Revision$, $Date$ */ public final class RevocationReason implements Serializable { private static final long serialVersionUID = -2582403666913588806L; public static final Collection INSTANCES = new ArrayList(); public static final Map CODES = new LinkedHashMap(); public static final Map LABELS = new LinkedHashMap(); /** * Reasons */ public static final RevocationReason UNSPECIFIED = new RevocationReason(0, "Unspecified"); public static final RevocationReason KEY_COMPROMISE = new RevocationReason(1, "Key_Compromise"); public static final RevocationReason CA_COMPROMISE = new RevocationReason(2, "CA_Compromise"); public static final RevocationReason AFFILIATION_CHANGED = new RevocationReason(3, "Affiliation_Changed"); public static final RevocationReason SUPERSEDED = new RevocationReason(4, "Superseded"); public static final RevocationReason CESSATION_OF_OPERATION = new RevocationReason(5, "Cessation_of_Operation"); public static final RevocationReason CERTIFICATE_HOLD = new RevocationReason(6, "Certificate_Hold"); public static final RevocationReason REMOVE_FROM_CRL = new RevocationReason(8, "Remove_from_CRL"); public static final RevocationReason PRIVILEGE_WITHDRAWN = new RevocationReason(9, "Privilege_Withdrawn"); public static final RevocationReason AA_COMPROMISE = new RevocationReason(10, "AA_Compromise"); // Private data members private int code; private String label; /** * Create a RevocationReason with the passed integer value and string label. * * @param reason integer value of the enumeration alternative. * @param label string value of the enumeration alternative. */ private RevocationReason(int reason, String label) { this.code = reason; this.label = label; INSTANCES.add(this); CODES.put(reason, this); LABELS.put(label.toLowerCase(), this); } public int getCode() { return code; } public String getLabel() { return label; } public static RevocationReason fromInt(int reason) { return valueOf(reason); } public static RevocationReason valueOf(int reason) { return CODES.get(reason); } public static RevocationReason valueOf(String string) { return LABELS.get(string.toLowerCase()); } public int toInt() { return code; } @Override public String toString() { return label; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; RevocationReason other = (RevocationReason) obj; if (code != other.code) return false; if (label == null) { if (other.label != null) return false; } else if (!label.equals(other.label)) return false; return true; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + code; result = prime * result + ((label == null) ? 0 : label.hashCode()); return result; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/RevokedCertImpl.java000066400000000000000000000354311412550063600300740ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.math.BigInteger; import java.security.cert.CRLException; import java.util.Date; import java.util.Enumeration; import java.util.LinkedHashSet; import java.util.Set; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** *

* Abstract class for a revoked certificate in a CRL. This class is for each entry in the * revokedCertificates, so it deals with the inner SEQUENCE. The ASN.1 definition for this is: * *

 * revokedCertificates    SEQUENCE OF SEQUENCE  {
 *     userCertificate    CertificateSerialNumber,
 *     revocationDate     ChoiceOfTime,
 *     crlEntryExtensions Extensions OPTIONAL
 *                        -- if present, must be v2
 * }  OPTIONAL
 *
 * CertificateSerialNumber  ::=  INTEGER
 *
 * Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
 *
 * Extension  ::=  SEQUENCE  {
 *     extnId        OBJECT IDENTIFIER,
 *     critical      BOOLEAN DEFAULT FALSE,
 *     extnValue     OCTET STRING
 *                   -- contains a DER encoding of a value
 *                   -- of the type registered for use with
 *                   -- the extnId object identifier value
 * }
 * 
* * @author Hemma Prafullchandra * @version 1.6 97/12/10 */ public class RevokedCertImpl extends RevokedCertificate implements Serializable { /** * */ private static final long serialVersionUID = -3449642360223397701L; private SerialNumber serialNumber; private Date revocationDate; private CRLExtensions extensions = null; private byte[] revokedCert; private final static boolean isExplicit = false; /** * Default constructor. */ public RevokedCertImpl() { } /** * Constructs a revoked certificate entry using the serial number and * revocation date. * * @param num * the serial number of the revoked certificate. * @param date * the Date on which revocation took place. */ public RevokedCertImpl(BigInteger num, Date date) { this.serialNumber = new SerialNumber(num); this.revocationDate = date; } /** * Constructs a revoked certificate entry using the serial number, * revocation date and the entry extensions. * * @param num * the serial number of the revoked certificate. * @param date * the Date on which revocation took place. * @param crlEntryExts * the extensions for this entry. */ public RevokedCertImpl(BigInteger num, Date date, CRLExtensions crlEntryExts) { this.serialNumber = new SerialNumber(num); this.revocationDate = date; this.extensions = crlEntryExts; } @Override public byte[] getEncoded() throws CRLException { // XXX NOT IMPLEMENTED if (revokedCert == null) { DerOutputStream os = new DerOutputStream(); try { encode(os); } catch (Exception e) { // revokedCert = null; } revokedCert = os.toByteArray(); } return revokedCert; } @Override public boolean hasUnsupportedCriticalExtension() { // XXX NOT IMPLEMENTED return true; } /** * Sets extensions for this impl. * * @param crlEntryExts * CRLExtensions */ public void setExtensions(CRLExtensions crlEntryExts) { this.extensions = crlEntryExts; } /** * Unmarshals a revoked certificate from its encoded form. * * @param revokedCert * the encoded bytes. * @exception CRLException * on parsing errors. * @exception X509ExtensionException * on extension handling errors. */ public RevokedCertImpl(byte[] revokedCert) throws CRLException, X509ExtensionException { try { DerValue derValue = new DerValue(revokedCert); parse(derValue); } catch (IOException e) { throw new CRLException("Parsing error: " + e.toString()); } } /** * Unmarshals a revoked certificate from its encoded form. * * @param derValue * the DER value containing the revoked certificate. * @exception CRLException * on parsing errors. * @exception X509ExtensionException * on extension handling errors. */ public RevokedCertImpl(DerValue derValue) throws CRLException, X509ExtensionException { parse(derValue); } /** * Returns true if this revoked certificate entry has extensions, otherwise * false. * * @return true if this CRL entry has extensions, otherwise false. */ @Override public boolean hasExtensions() { if (extensions == null) return false; else return true; } /** * Decode a revoked certificate from an input stream. * * @param inStrm * an input stream holding at least one revoked certificate * @exception CRLException * on parsing errors. * @exception X509ExtensionException * on extension handling errors. */ public void decode(InputStream inStrm) throws CRLException, X509ExtensionException { try { DerValue derValue = new DerValue(inStrm); parse(derValue); } catch (IOException e) { throw new CRLException("Parsing error: " + e.toString()); } } /** * Encodes the revoked certificate to an output stream. * * @param outStrm * an output stream to which the encoded revoked certificate is * written. * @exception CRLException * on encoding errors. * @exception X509ExtensionException * on extension handling errors. */ public void encode(DerOutputStream outStrm) throws CRLException, X509ExtensionException { try (DerOutputStream seq = new DerOutputStream()) { if (revokedCert == null) { DerOutputStream tmp = new DerOutputStream(); // sequence { serialNumber, revocationDate, extensions } serialNumber.encode(tmp); // from 2050 should encode GeneralizedTime tmp.putUTCTime(revocationDate); if (extensions != null) extensions.encode(tmp, isExplicit); seq.write(DerValue.tag_Sequence, tmp); revokedCert = seq.toByteArray(); } outStrm.write(revokedCert); } catch (IOException e) { throw new CRLException("Encoding error: " + e.toString()); } } /** * Gets the serial number for this RevokedCertificate, the userCertificate. * * @return the serial number. */ @Override public BigInteger getSerialNumber() { return serialNumber.getNumber().toBigInteger(); } /** * Gets the revocation date for this RevokedCertificate, the revocationDate. * * @return the revocation date. */ @Override public Date getRevocationDate() { return (new Date(revocationDate.getTime())); } /** * Returns extensions for this impl. * * @return the CRLExtensions */ @Override public CRLExtensions getExtensions() { return extensions; } /** * Returns a printable string of this revoked certificate. * * @return value of this revoked certificate in a printable form. */ @Override public String toString() { StringBuffer sb = new StringBuffer(serialNumber.toString() + " On: " + revocationDate.toString()); if (extensions != null) { sb.append("\n"); for (int i = 0; i < extensions.size(); i++) sb.append("Entry Extension[" + i + "]: " + (extensions.elementAt(i)).toString()); } sb.append("\n"); return (sb.toString()); } /** * Gets a Set of the extension(s) marked CRITICAL in the * RevokedCertificate by OID strings. * * @return a set of the extension oid strings in the * Object that are marked critical. */ @Override public Set getCriticalExtensionOIDs() { if (extensions == null) return null; Set extSet = new LinkedHashSet(); Extension ex; for (Enumeration e = extensions.getElements(); e.hasMoreElements();) { ex = e.nextElement(); if (ex.isCritical()) extSet.add(ex.getExtensionId().toString()); } return extSet; } /** * Gets a Set of the extension(s) marked NON-CRITICAL in the * RevokedCertificate by OID strings. * * @return a set of the extension oid strings in the * Object that are marked critical. */ @Override public Set getNonCriticalExtensionOIDs() { if (extensions == null) return null; Set extSet = new LinkedHashSet(); Extension ex; for (Enumeration e = extensions.getElements(); e.hasMoreElements();) { ex = e.nextElement(); if (!ex.isCritical()) extSet.add(ex.getExtensionId().toString()); } return extSet; } /** * Gets the DER encoded OCTET string for the extension value * (extnValue) identified by the passed in oid String. * The oid string is * represented by a set of positive whole number separated * by ".", that means,
* <positive whole number>.<positive whole number>.<positive * whole number>.<...> * * @param oid the Object Identifier value for the extension. * @return the DER encoded octet string of the extension value. */ @Override public byte[] getExtensionValue(String oid) { if (extensions == null) return null; try (DerOutputStream out = new DerOutputStream()) { String extAlias = OIDMap.getName(new ObjectIdentifier(oid)); Extension crlExt = null; if (extAlias == null) { // may be unknown ObjectIdentifier findOID = new ObjectIdentifier(oid); Extension ex = null; ObjectIdentifier inCertOID; for (Enumeration e = extensions.getElements(); e.hasMoreElements();) { ex = e.nextElement(); inCertOID = ex.getExtensionId(); if (inCertOID.equals(findOID)) { crlExt = ex; break; } } } else crlExt = extensions.get(extAlias); if (crlExt == null) return null; byte[] extData = crlExt.getExtensionValue(); if (extData == null) return null; out.putOctetString(extData); return out.toByteArray(); } catch (Exception e) { return null; } } private void parse(DerValue derVal) throws CRLException, X509ExtensionException { if (derVal.tag != DerValue.tag_Sequence) { throw new CRLException("Invalid encoded RevokedCertificate, " + "starting sequence tag missing."); } if (derVal.data.available() == 0) throw new CRLException("No data encoded for RevokedCertificates"); // serial number try { DerInputStream in = derVal.toDerInputStream(); DerValue val = in.getDerValue(); this.serialNumber = new SerialNumber(val); } catch (IOException e) { throw new CRLException("Parsing Serial Number error: " + e.toString()); } // revocationDate try { int nextByte = derVal.data.peekByte(); if ((byte) nextByte == DerValue.tag_UtcTime) { this.revocationDate = derVal.data.getUTCTime(); } else if ((byte) nextByte == DerValue.tag_GeneralizedTime) { this.revocationDate = derVal.data.getGeneralizedTime(); } else { throw new CRLException("Invalid encoding for RevokedCertificates"); } } catch (IOException e) { throw new CRLException("Parsing Revocation Date error: " + e.toString()); } if (derVal.data.available() == 0) return; // no extensions // crlEntryExtensions try { this.extensions = new CRLExtensions(derVal.toDerInputStream()); } catch (IOException e) { throw new CRLException("Parsing CRL Entry Extensions error: " + e.toString()); } } /** * Serialization write ... X.509 certificates serialize as themselves, and * they're parsed when they get read back. (Actually they serialize as some * type data from the serialization subsystem, then the cert data.) */ private void writeObject(ObjectOutputStream stream) throws CRLException, X509ExtensionException, IOException { DerOutputStream dos = new DerOutputStream(); encode(dos); dos.derEncode(stream); } /** * Serialization read ... X.509 certificates serialize as themselves, and * they're parsed when they get read back. */ private void readObject(ObjectInputStream stream) throws CRLException, X509ExtensionException, IOException { decode(stream); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/RevokedCertificate.java000066400000000000000000000056151412550063600306000ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.math.BigInteger; import java.security.cert.X509CRL; import java.security.cert.X509CRLEntry; import java.util.Date; /** *

* Abstract class for a revoked certificate in a CRL (Certificate Revocation List). * * The ASN.1 definition for revokedCertificates is: * *

 *  revokedCertificates    SEQUENCE OF SEQUENCE  {
 *      userCertificate    CertificateSerialNumber,
 *      revocationDate     ChoiceOfTime,
 *      crlEntryExtensions Extensions OPTIONAL
 *                         -- if present, must be v2
 *  }  OPTIONAL
 *  CertificateSerialNumber  ::=  INTEGER
 *  Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
 *  Extension  ::=  SEQUENCE  {
 *      extnId        OBJECT IDENTIFIER,
 *      critical      BOOLEAN DEFAULT FALSE,
 *      extnValue     OCTET STRING
 *                    -- contains a DER encoding of a value
 *                    -- of the type registered for use with
 *                    -- the extnId object identifier value
 *  }
 * 
* * @see X509CRL * * @author Hemma Prafullchandra * @version 1.4 97/12/10 */ public abstract class RevokedCertificate extends X509CRLEntry { /* implements X509Extension { */ /** * Gets the serial number for this RevokedCertificate, * the userCertificate. * * @return the serial number. */ @Override public abstract BigInteger getSerialNumber(); /** * Gets the revocation date for this RevokedCertificate, * the revocationDate. * * @return the revocation date. */ @Override public abstract Date getRevocationDate(); /** * Returns true if this revoked certificate entry has * extensions. * * @return true if this entry has extensions, false otherwise. */ @Override public abstract boolean hasExtensions(); /** * Returns a string representation of this revoked certificate. * * @return a string representation of this revoked certificate. */ @Override public abstract String toString(); public abstract CRLExtensions getExtensions(); } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/SerialNumber.java000066400000000000000000000075121412550063600274240ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.math.BigInteger; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class defines the SerialNumber class used by certificates. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.5 */ public class SerialNumber implements Serializable { private static final long serialVersionUID = 1600956411497203535L; private BigInt serialNum; // Construct the class from the DerValue private void construct(DerValue derVal) throws IOException { serialNum = derVal.getInteger(); if (derVal.data.available() != 0) { throw new IOException("Excess SerialNumber data"); } } /** * The default constructor for this class using BigInteger. * * @param num the BigInteger number used to create the serial number. */ public SerialNumber(BigInteger num) { serialNum = new BigInt(num); } public SerialNumber(BigInt num) { serialNum = num; } /** * The default constructor for this class using int. * * @param num the BigInteger number used to create the serial number. */ public SerialNumber(int num) { serialNum = new BigInt(num); } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the SerialNumber from. * @exception IOException on decoding errors. */ public SerialNumber(DerInputStream in) throws IOException { DerValue derVal = in.getDerValue(); construct(derVal); } /** * Create the object, decoding the values from the passed DerValue. * * @param val the DerValue to read the SerialNumber from. * @exception IOException on decoding errors. */ public SerialNumber(DerValue val) throws IOException { construct(val); } /** * Create the object, decoding the values from the passed stream. * * @param in the InputStream to read the SerialNumber from. * @exception IOException on decoding errors. */ public SerialNumber(InputStream in) throws IOException { DerValue derVal = new DerValue(in); construct(derVal); } /** * Return the SerialNumber as user readable string. */ @Override public String toString() { return ("SerialNumber: [" + serialNum.toString() + "]"); } /** * Encode the SerialNumber in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @exception IOException on errors. */ public void encode(DerOutputStream out) throws IOException { out.putInteger(serialNum); } /** * Return the serial number. */ public BigInt getNumber() { return (serialNum); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/SubjectAlternativeNameExtension.java000066400000000000000000000200141412550063600333200ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This represents the Subject Alternative Name Extension. * * This extension, if present, allows the subject to specify multiple * alternative names. * *

* Extensions are represented as a sequence of the extension identifier (Object Identifier), a boolean flag stating * whether the extension is to be treated as being critical and the extension value itself (this is again a DER encoding * of the extension value). *

* The ASN.1 syntax for this is: * *

 * SubjectAltName ::= GeneralNames
 * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
 * 
* * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.9 * @see Extension * @see CertAttrSet */ public class SubjectAlternativeNameExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -4022446008355607196L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.SubjectAlternativeName"; /** * Attribute names. */ public static final String NAME = "SubjectAlternativeName"; public static final String SUBJECT_NAME = "subject_name"; // private data members GeneralNames names; // Encode this extension private void encodeThis() throws IOException { DerOutputStream os = new DerOutputStream(); try { names.encode(os); } catch (GeneralNamesException e) { throw new IOException("SubjectAlternativeName: " + e); } extensionValue = os.toByteArray(); } /** * Create a SubjectAlternativeNameExtension with the passed GeneralNames. * * @param names the GeneralNames for the subject. * @exception IOException on error. */ public SubjectAlternativeNameExtension(boolean critical, GeneralNames names) throws IOException { this.names = names; this.extensionId = PKIXExtensions.SubjectAlternativeName_Id; this.critical = critical; encodeThis(); } public SubjectAlternativeNameExtension(GeneralNames names) throws IOException { this.names = names; this.extensionId = PKIXExtensions.SubjectAlternativeName_Id; this.critical = false; encodeThis(); } /** * Create a default SubjectAlternativeNameExtension. */ public SubjectAlternativeNameExtension() { extensionId = PKIXExtensions.SubjectAlternativeName_Id; critical = false; names = new GeneralNames(); } /** * Create the extension from the passed DER encoded value. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public SubjectAlternativeNameExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.SubjectAlternativeName_Id; this.critical = critical.booleanValue(); if (!(value instanceof byte[])) throw new IOException("SubjectAlternativeName: " + "Illegal argument type"); int len = Array.getLength(value); byte[] extValue = new byte[len]; System.arraycopy(value, 0, extValue, 0, len); this.extensionValue = extValue; DerValue val = new DerValue(extValue); try { names = new GeneralNames(val); } catch (GeneralNamesException e) { throw new IOException("SubjectAlternativeName: " + e, e); } } /** * Returns a printable representation of the SubjectAlternativeName. */ @Override public String toString() { if (names == null) return ""; String s = super.toString() + "SubjectAlternativeName [\n" + names.toString() + "]\n"; return (s); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Write the extension to the OutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on encoding errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { extensionId = PKIXExtensions.SubjectAlternativeName_Id; //critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { clearValue(); if (name.equalsIgnoreCase(SUBJECT_NAME)) { if (!(obj instanceof GeneralNames)) { throw new IOException("Attribute value should be of " + "type GeneralNames."); } names = (GeneralNames) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:SubjectAlternativeName."); } } /** * Set the GeneralNames of this extension. */ public void setGeneralNames(GeneralNames names) { clearValue(); this.names = names; } /** * Get the GeneralNames of this extension. */ public GeneralNames getGeneralNames() { return names; } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(SUBJECT_NAME)) { return (names); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:SubjectAlternativeName."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(SUBJECT_NAME)) { names = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:SubjectAlternativeName."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(SUBJECT_NAME); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/SubjectDirAttributesExtension.java000066400000000000000000000213121412550063600330300ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class represents the Subject Directory Attributes Extension. * *

* The subject directory attributes extension is not recommended as an essential part of this profile, but it may be * used in local environments. This extension MUST be non-critical. * *

 * The ASN.1 syntax for this extension is:
 *
 *    SubjectDirectoryAttributes ::= SEQUENCE (1..MAX) OF Attribute
 *
 *    Attribute	::= SEQUENCE {
 * type		AttributeType,
 * 	value		SET OF AttributeValue
 *              	-- at least one value is required --}
 *
 *    AttributeType	::= OBJECT IDENTIFIER
 *
 *    AttributeValue	::= ANY
 *
 * 
* * @author Christine Ho * @version 1.7 * * @see CertAttrSet * @see Extension */ public class SubjectDirAttributesExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = -1215458115428197688L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ //public static final String IDENT = "x509.info.extensions.SubjectDirectoryAttributes"; public static final String IDENT = "Subject Directory Attributes"; /** * Attribute names. */ public static final String NAME = "SubjectDirectoryAttributes"; // Private data members private Vector attrList = new Vector(); // Encode this extension value private void encodeThis() throws IOException { try (DerOutputStream out = new DerOutputStream()) { DerOutputStream tmp = new DerOutputStream(); //encoding the attributes Enumeration attrs = attrList.elements(); while (attrs.hasMoreElements()) { Attribute attr = attrs.nextElement(); attr.encode(tmp); } out.write(DerValue.tag_SequenceOf, tmp); this.extensionValue = out.toByteArray(); } } // Decode this extension value private void decodeThis(DerValue derVal) throws IOException { if (derVal.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for " + "Subject Directory Attribute extension."); } if (derVal.data.available() == 0) { throw new IOException(NAME + " No data available in " + "passed DER encoded value."); } // Decode all the Attributes while (derVal.data.available() != 0) { DerValue encAttr = derVal.data.getDerValue(); Attribute attr = new Attribute(encAttr); attrList.addElement(attr); } } /** * Default constructor for this object. * * @param derVal Der encoded value of this extension */ public SubjectDirAttributesExtension(DerValue derVal) throws IOException { this.extensionId = PKIXExtensions.SubjectDirectoryAttributes_Id; this.critical = false; decodeThis(derVal); } /** * Default constructor for this object. * * @param list Attribute object list */ public SubjectDirAttributesExtension(Attribute[] list) throws IOException { this.extensionId = PKIXExtensions.SubjectDirectoryAttributes_Id; this.critical = false; if ((list == null) || (list.length == 0)) { throw new IOException("No data available in " + "passed Attribute List."); } // add the Attributes for (int i = 0; i < list.length; i++) { attrList.addElement(list[i]); } } /** * Constructor from parsing extension */ public SubjectDirAttributesExtension(Boolean crit, Object value) throws IOException { this.extensionId = PKIXExtensions.SubjectDirectoryAttributes_Id; this.critical = crit.booleanValue(); if (!(value instanceof byte[])) throw new IOException(NAME + "Illegal argument type"); int len = Array.getLength(value); byte[] extValue = new byte[len]; System.arraycopy(value, 0, extValue, 0, len); this.extensionValue = extValue; decodeThis(new DerValue(extValue)); } /** * Constructor for this object. * * @param list Attribute object list * @param critical The criticality */ public SubjectDirAttributesExtension(Attribute[] list, boolean critical) throws IOException { this.extensionId = PKIXExtensions.SubjectDirectoryAttributes_Id; this.critical = critical; if ((list == null) || (list.length == 0)) { throw new IOException("No data available in " + "passed Attribute List."); } // add the Attributes for (int i = 0; i < list.length; i++) { attrList.addElement(list[i]); } } /** * Return user readable form of extension. */ @Override public String toString() { String s = super.toString() + "SubjectDirectoryAttributes:[\n"; Enumeration attrs = attrList.elements(); StringBuffer tempBuffer = new StringBuffer(); while (attrs.hasMoreElements()) { Attribute attr = attrs.nextElement(); tempBuffer.append(attr.toString()); } s += tempBuffer.toString(); return (s + "]\n"); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { DerValue val = new DerValue(in); decodeThis(val); } /** * Encode this extension value to the output stream. * * @param out the DerOutputStream to encode the extension to. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { this.extensionId = PKIXExtensions.SubjectDirectoryAttributes_Id; this.critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { throw new IOException("Attribute name not recognized by " + "CertAttrSet:SubjectDirectoryAttributes."); } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { throw new IOException("Attribute name not recognized by " + "CertAttrSet:SubjectDirectoryAttributes."); } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { throw new IOException("Attribute name not recognized by " + "CertAttrSet:SubjectDirectoryAttributes."); } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } /** * Returns an enumeration of attributes in the extension. */ public Enumeration getAttributesList() { if (attrList == null) return null; return attrList.elements(); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/SubjectKeyIdentifierExtension.java000066400000000000000000000162021412550063600330000ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Array; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * Represent the Subject Key Identifier Extension. * * This extension, if present, provides a means of identifying the particular * public key used in an application. This extension by default is marked * non-critical. * *

* Extensions are addiitonal attributes which can be inserted in a X509 v3 certificate. For example a * "Driving License Certificate" could have the driving license number as a extension. * *

* Extensions are represented as a sequence of the extension identifier (Object Identifier), a boolean flag stating * whether the extension is to be treated as being critical and the extension value itself (this is again a DER encoding * of the extension value). * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.7 * @see Extension * @see CertAttrSet */ public class SubjectKeyIdentifierExtension extends Extension implements CertAttrSet { /** * */ private static final long serialVersionUID = 2457721262590880939L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info.extensions.SubjectKeyIdentifier"; /** * Attribute names. */ public static final String NAME = "SubjectKeyIdentifier"; public static final String KEY_ID = "key_id"; // Private data member private KeyIdentifier id; // Encode this extension value private void encodeThis() throws IOException { DerOutputStream os = new DerOutputStream(); id.encode(os); extensionValue = os.toByteArray(); } /** * Create a SubjectKeyIdentifierExtension with the passed octet string. * The criticality is set to False. * * @param octetString the octet string identifying the key identifier. */ public SubjectKeyIdentifierExtension(boolean critical, byte[] octetString) throws IOException { id = new KeyIdentifier(octetString); this.extensionId = PKIXExtensions.SubjectKey_Id; this.critical = critical; encodeThis(); } public SubjectKeyIdentifierExtension(byte[] octetString) throws IOException { id = new KeyIdentifier(octetString); this.extensionId = PKIXExtensions.SubjectKey_Id; this.critical = false; encodeThis(); } /** * Create the extension from the passed DER encoded value. * * @param critical true if the extension is to be treated as critical. * @param value Array of DER encoded bytes of the actual value. * @exception IOException on error. */ public SubjectKeyIdentifierExtension(Boolean critical, Object value) throws IOException { this.extensionId = PKIXExtensions.SubjectKey_Id; this.critical = critical.booleanValue(); int len = Array.getLength(value); byte[] extValue = new byte[len]; for (int i = 0; i < len; i++) { extValue[i] = Array.getByte(value, i); } this.extensionValue = extValue; DerValue val = new DerValue(extValue); this.id = new KeyIdentifier(val); } /** * Returns a printable representation. */ @Override public String toString() { if (id == null) return ""; String s = super.toString() + "SubjectKeyIdentifier [\n" + id.toString() + "]\n"; return (s); } /** * Write the extension to the OutputStream. * * @param out the OutputStream to write the extension to. * @exception IOException on encoding errors. */ @Override public void encode(OutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); if (extensionValue == null) { extensionId = PKIXExtensions.SubjectKey_Id; critical = false; encodeThis(); } super.encode(tmp); out.write(tmp.toByteArray()); } /** * Decode the extension from the InputStream. * * @param in the InputStream to unmarshal the contents from. * @exception IOException on decoding or validity errors. */ @Override public void decode(InputStream in) throws IOException { throw new IOException("Method not to be called directly."); } /** * Set the attribute value. */ @Override public void set(String name, Object obj) throws IOException { clearValue(); if (name.equalsIgnoreCase(KEY_ID)) { if (!(obj instanceof KeyIdentifier)) { throw new IOException("Attribute value should be of" + " type KeyIdentifier."); } id = (KeyIdentifier) obj; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:SubjectKeyIdentifierExtension."); } } /** * Get the attribute value. */ @Override public Object get(String name) throws IOException { if (name.equalsIgnoreCase(KEY_ID)) { return (id); } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:SubjectKeyIdentifierExtension."); } } /** * Delete the attribute value. */ @Override public void delete(String name) throws IOException { if (name.equalsIgnoreCase(KEY_ID)) { id = null; } else { throw new IOException("Attribute name not recognized by " + "CertAttrSet:SubjectKeyIdentifierExtension."); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(KEY_ID); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/URIName.java000066400000000000000000000046541412550063600263000ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class implements the URIName as required by the GeneralNames * ASN.1 object. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.3 * @see GeneralName * @see GeneralNames * @see GeneralNameInterface */ public class URIName implements GeneralNameInterface { /** * */ private static final long serialVersionUID = 8340049830612859508L; private String name; /** * Create the URIName object from the passed encoded Der value. * * @param derValue the encoded DER URIName. * @exception IOException on error. */ public URIName(DerValue derValue) throws IOException { name = derValue.getIA5String(); } /** * Create the URIName object with the specified name. * * @param name the URIName. */ public URIName(String name) { this.name = name; } /** * Return the type of the GeneralName. */ @Override public int getType() { return (GeneralNameInterface.NAME_URI); } /** * Encode the URI name into the DerOutputStream. * * @param out the DER stream to encode the URIName to. * @exception IOException on encoding errors. */ @Override public void encode(DerOutputStream out) throws IOException { out.putIA5String(name); } /** * Convert the name into user readable string. */ @Override public String toString() { return ("URIName: " + name); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/UniqueIdentity.java000066400000000000000000000064701412550063600300160ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import org.mozilla.jss.netscape.security.util.BitArray; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * This class defines the UniqueIdentity class used by certificates. * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.6 */ public class UniqueIdentity { // Private data members private BitArray id; /** * The default constructor for this class. * * @param id the byte array containing the unique identifier. */ public UniqueIdentity(BitArray id) { this.id = id; } /** * The default constructor for this class. * * @param id the byte array containing the unique identifier. */ public UniqueIdentity(byte[] id) { this.id = new BitArray(id.length * 8, id); } /** * Create the object, decoding the values from the passed DER stream. * * @param in the DerInputStream to read the UniqueIdentity from. * @exception IOException on decoding errors. */ public UniqueIdentity(DerInputStream in) throws IOException { DerValue derVal = in.getDerValue(); id = derVal.getUnalignedBitString(true); } /** * Create the object, decoding the values from the passed DER stream. * * @param derVal the DerValue decoded from the stream. * @exception IOException on decoding errors. */ public UniqueIdentity(DerValue derVal) throws IOException { id = derVal.getUnalignedBitString(true); } /** * Return the UniqueIdentity as a printable string. */ @Override public String toString() { return ("UniqueIdentity:" + id.toString() + "\n"); } /** * Encode the UniqueIdentity in DER form to the stream. * * @param out the DerOutputStream to marshal the contents to. * @param tag enocode it under the following tag. * @exception IOException on errors. */ public void encode(DerOutputStream out, byte tag) throws IOException { byte[] bytes = id.toByteArray(); int excessBits = bytes.length * 8 - id.length(); out.write(tag); out.putLength(bytes.length + 1); out.write(excessBits); out.write(bytes); } /** * Return the unique id. */ public boolean[] getId() { if (id == null) return null; return id.toBooleanArray(); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/UserNotice.java000066400000000000000000000056531412550063600271200ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * Represent the UserNotice Qualifier. * * UserNotice ::= SEQUENCE { * noticeRef NoticeReference OPTIONAL, * explicitText DisplayText OPTIONAL * } * * @author Thomas Kwan */ public class UserNotice extends Qualifier { /** * */ private static final long serialVersionUID = 5770869942793748051L; private NoticeReference mNoticeReference = null; private DisplayText mDisplayText = null; public UserNotice(NoticeReference ref, DisplayText text) { mNoticeReference = ref; mDisplayText = text; } public UserNotice(DerValue val) throws IOException { if (val.tag != DerValue.tag_Sequence) { throw new IOException("Invalid encoding for UserNotice"); } // case 0: no element if (val.data.available() == 0) return; // case 1: 1 element DerValue inSeq = val.data.getDerValue(); if (inSeq.tag == DerValue.tag_Sequence) { mNoticeReference = new NoticeReference(inSeq); } else { mDisplayText = new DisplayText(inSeq); } if (val.data.available() == 0) return; // case 2: 2 elements mDisplayText = new DisplayText(val.data.getDerValue()); } public NoticeReference getNoticeReference() { return mNoticeReference; } public DisplayText getDisplayText() { return mDisplayText; } /** * Write the UserNotice to the DerOutputStream. * * @param out the DerOutputStream to write the object to. * @exception IOException on errors. */ @Override public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); // OPTIONAL if (mNoticeReference != null) { mNoticeReference.encode(tmp); } // OPTIONAL if (mDisplayText != null) { mDisplayText.encode(tmp); } out.write(DerValue.tag_Sequence, tmp); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/X500Name.java000066400000000000000000000535251412550063600262760ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.security.Principal; import java.util.ArrayList; import java.util.Arrays; import java.util.Enumeration; import java.util.List; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** * X.500 names are used to identify entities, such as those which are * identified by X.509 certificates. They are world-wide, hierarchical, * and descriptive. Entities can be identified by attributes, and in * some systems can be searched for according to those attributes. * *

* This class exposes only partial X.500 name functionality. Most * notably, it works best if Relative Distinguished Names only have one * (unique) attribute each, and if only the most common attributes need * to be visible to applications. This limitation, and others, will * be lifted over time. * * @author David Brownell * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.35 * @see GeneralName * @see GeneralNames * @see GeneralNameInterface * @see RDN * @see AVA * @see LdapDNStrConverter */ public class X500Name implements Principal, GeneralNameInterface { /** * */ private static final long serialVersionUID = -730790062013191108L; /** * Constructs a name from a Ldap DN string, such * as "CN=Dave, OU=JavaSoft, O=Sun Microsystems, C=US". The * older "/C=US/O=Sun Microsystems, Inc/OU=JavaSoft/CN=Dave" syntax * is not currently supported. (The former is RFC 1779 style.) * * @param ldapDNString a Ldap DN String e.g. as defined in RFC1779 */ public X500Name(String ldapDNString) throws IOException { X500Name x500name; if (ldapDNString == null || ldapDNString.equals("")) { clear(); return; } x500name = LdapDNStrConverter.getDefault().parseDN(ldapDNString); names = x500name.getNames(); } /** * Constructs a X500Name from a Ldap DN String using the specified * LdapDNStrConverter. Also use the input tags. * * @see LdapDNStrConverter * * @param ldapDNString a Ldap DN String e.g. as defined in RFC1779. * @param ldapDNStrConverter A LdapDNStrConverter */ public X500Name(String ldapDNString, LdapDNStrConverter ldapDNStrConverter, byte[] tags) throws IOException { if (ldapDNString == null || ldapDNString.equals("")) { clear(); return; } X500Name x500name; x500name = ldapDNStrConverter.parseDN(ldapDNString, tags); names = x500name.getNames(); } public X500Name(String ldapDNString, byte[] tags) throws IOException { if (ldapDNString == null || ldapDNString.equals("")) { clear(); return; } X500Name x500name; x500name = LdapDNStrConverter.getDefault().parseDN(ldapDNString, tags); names = x500name.getNames(); } /** * Constructs a X500Name from a Ldap DN String using the specified * LdapDNStrConverter. * * @see LdapDNStrConverter * * @param ldapDNString a Ldap DN String e.g. as defined in RFC1779. * @param ldapDNStrConverter A LdapDNStrConverter */ public X500Name(String ldapDNString, LdapDNStrConverter ldapDNStrConverter) throws IOException { if (ldapDNString == null || ldapDNString.equals("")) { clear(); return; } X500Name x500name; x500name = ldapDNStrConverter.parseDN(ldapDNString); names = x500name.getNames(); } /** * Constructs a X500Name from fields common in enterprise application * environments. * * @param commonName common name of a person, e.g. "Vivette Davis" * @param organizationUnit small organization name, e.g. "Purchasing" * @param organizationName large organization name, e.g. "Onizuka, Inc." * @param country two letter country code, e.g. "CH" */ public X500Name( String commonName, String organizationUnit, String organizationName, String country) throws IOException { DirStrConverter dirStrConverter = new DirStrConverter(); PrintableConverter printableConverter = new PrintableConverter(); AVA[] assertion = new AVA[1]; // array is cloned in constructors. int i = 4; names = new RDN[i]; /* * NOTE: it's only on output that little-endian * ordering is used. */ assertion[0] = new AVA(commonName_oid, dirStrConverter.getValue(commonName)); names[--i] = new RDN(assertion); assertion[0] = new AVA(orgUnitName_oid, dirStrConverter.getValue(organizationUnit)); names[--i] = new RDN(assertion); assertion[0] = new AVA(orgName_oid, dirStrConverter.getValue(organizationName)); names[--i] = new RDN(assertion); assertion[0] = new AVA(countryName_oid, printableConverter.getValue(country)); names[--i] = new RDN(assertion); } /** * Constructs a X500Name from fields common in Internet application * environments. * * @param commonName common name of a person, e.g. "Vivette Davis" * @param organizationUnit small organization name, e.g. "Purchasing" * @param organizationName large organization name, e.g. "Onizuka, Inc." * @param localityName locality (city) name, e.g. "Palo Alto" * @param stateName state name, e.g. "California" * @param country two letter country code, e.g. "CH" */ public X500Name( String commonName, String organizationUnit, String organizationName, String localityName, String stateName, String country) throws IOException { DirStrConverter dirStrConverter = new DirStrConverter(); PrintableConverter printableConverter = new PrintableConverter(); AVA[] assertion = new AVA[1]; // array is cloned in constructors. int i = 6; names = new RDN[i]; /* * NOTE: it's only on output that little-endian * ordering is used. */ assertion[0] = new AVA(commonName_oid, dirStrConverter.getValue(commonName)); names[--i] = new RDN(assertion); assertion[0] = new AVA(orgUnitName_oid, dirStrConverter.getValue(organizationUnit)); names[--i] = new RDN(assertion); assertion[0] = new AVA(orgName_oid, dirStrConverter.getValue(organizationName)); names[--i] = new RDN(assertion); assertion[0] = new AVA(localityName_oid, dirStrConverter.getValue(localityName)); names[--i] = new RDN(assertion); assertion[0] = new AVA(stateName_oid, dirStrConverter.getValue(stateName)); names[--i] = new RDN(assertion); assertion[0] = new AVA(countryName_oid, printableConverter.getValue(country)); names[--i] = new RDN(assertion); } /** * Constructs a name from an ASN.1 encoded value. The encoding * of the name in the stream uses DER (a BER/1 subset). * * @param value a DER-encoded value holding an X.500 name. */ public X500Name(DerValue value) throws IOException { this(value.toDerInputStream()); } /** * Constructs a name from an ASN.1 encoded input stream. The encoding * of the name in the stream uses DER (a BER/1 subset). * * @param in DER-encoded data holding an X.500 name. */ public X500Name(DerInputStream in) throws IOException { parseDER(in); } /** * Constructs a name from an ASN.1 encoded byte array. * * @param name DER-encoded byte array holding an X.500 name. */ public X500Name(byte[] name) throws IOException { DerInputStream in = new DerInputStream(name); parseDER(in); } /** * Constructs a X500Name from array of RDN. The RDNs are expected to * be in big endian order i.e. most significant first. * * @param rdns an array of RDN. */ public X500Name(RDN[] rdns) throws IOException { names = rdns.clone(); } /** * convenience method. * * @param rdnVector a vector of rdns. */ public X500Name(Vector rdnVector) throws IOException { int size = rdnVector.size(); names = new RDN[size]; for (int i = 0; i < size; i++) { names[i] = rdnVector.elementAt(i); } } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + Arrays.hashCode(names); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; X500Name other = (X500Name) obj; if (!Arrays.equals(names, other.names)) return false; return true; } /** * Sets private data to a null state */ private void clear() { dn = ""; names = null; } /** * Returns the name component as a Java string, regardless of its * encoding restrictions. */ private String getString(DerValue attribute) throws IOException { String value = attribute.getAsString(); if (value == null) throw new IOException("not a DER string encoding, " + attribute.tag); else return value; } /** * Return type of GeneralName. */ @Override public int getType() { return (GeneralNameInterface.NAME_DIRECTORY); } /** * Returns a "Country" name component. If more than one * such attribute exists, the topmost one is returned. * * @return "C=" component of the name, if any. */ public String getCountry() throws IOException { DerValue attr = findAttribute(countryName_oid); return getString(attr); } /** * Returns an "Organization" name component. If more than * one such attribute exists, the topmost one is returned. * * @return "O=" component of the name, if any. */ public String getOrganization() throws IOException { DerValue attr = findAttribute(orgName_oid); return getString(attr); } /** * Returns an "Organizational Unit" name component. If more * than one such attribute exists, the topmost one is returned. * * @return "OU=" component of the name, if any. */ public String getOrganizationalUnit() throws IOException { DerValue attr = findAttribute(orgUnitName_oid); return getString(attr); } /** * Returns a "Common Name" component. If more than one such * attribute exists, the topmost one is returned. * * @return "CN=" component of the name, if any. */ public String getCommonName() throws IOException { DerValue attr = findAttribute(commonName_oid); return getString(attr); } /** * Returns a "UID" component. If more than one such * attribute exists, the topmost one is returned. * * @return "UID=" component of the name, if any. */ public String getUserID() throws IOException { DerValue attr = findAttribute(uidName_oid); return getString(attr); } /** * Returns a "Locality" name component. If more than one * such component exists, the topmost one is returned. * * @return "L=" component of the name, if any. */ public String getLocality() throws IOException { DerValue attr = findAttribute(localityName_oid); return getString(attr); } /** * Returns a "State" name component. If more than one * such component exists, the topmost one is returned. * * @return "S=" component of the name, if any. */ public String getState() throws IOException { DerValue attr = findAttribute(stateName_oid); return getString(attr); } /** * Returns a "Email" name component. If more than one * such component exists, the topmost one is returned. * * @return "E=" component of the name, if any. */ public String getEmail() throws IOException { DerValue attr = findAttribute(email_oid); if (attr == null) return null; return getString(attr); } /** * Returns a Ldap DN String from the X500Name using the global default * LdapDNStrConverter * * @see LdapDNStrConverter * @return Ldap DN string of this X500Name using the default converter. */ public String toLdapDNString() throws IOException { if (dn == null) generateDN(LdapDNStrConverter.getDefault()); return dn; } /** * Return a list of attributes of the given type. * * The "most specific" value comes last. * * If there are no name attributes of the given type, an empty * list is returned. */ public List getAttributesForOid(ObjectIdentifier oid) throws IOException { List xs = new ArrayList<>(); for (int i = 0; i < names.length; i++) { DerValue v = names[i].findAttribute(oid); if (v != null) xs.add(getString(v)); } return xs; } /** * Returns a Ldap DN String from the X500Name * using the specified LdapDNStrconverter. * For example, RFC1779String converter can be passed to convert the * DN to RFC1779 string syntax. * * @see LdapDNStrConverter * @param ldapDNStrConverter a LdapDNStrConverter * @return Ldap DN string of the X500Name */ public String toLdapDNString(LdapDNStrConverter ldapDNStrConverter) throws IOException { if (dn == null) generateDN(ldapDNStrConverter); return dn; } /** * Returns a Ldap DN string, using the global default LdapDNStrConverter * or null if an error occurs in the conversion. */ @Override public String toString() { String s; if (names == null) { s = ""; return s; } try { s = toLdapDNString(); } catch (IOException e) { return null; } return s; } /** * Returns the value of toString(). This call is needed to * implement the java.security.Principal interface. */ @Override public String getName() { return toString(); } private String dn; // RFC 1779 style DN, or null private RDN names[]; // RDNs /** * Find the first instance of this attribute in a "top down" * search of all the attributes in the name. */ private DerValue findAttribute(ObjectIdentifier attribute) { int i; DerValue retval = null; for (i = 0; i < names.length; i++) { retval = names[i].findAttribute(attribute); if (retval != null) break; } return retval; } /** * Returns an enumerator of RDNs in the X500Name. * * @return enumeration of rdns in this X500Name. */ public Enumeration getRDNs() { return new RDNEnumerator(); } /** * Returns an array of RDN in the X500Name. * * @return array of RDN in this X500name. */ public RDN[] getNames() { return names.clone(); } /** * Returns the number of RDNs in the X500Name. * * @return number of RDNs in this X500Name. */ public int getNamesLength() { return names.length; } /****************************************************************/ private void parseDER(DerInputStream in) throws IOException { // // X.500 names are a "SEQUENCE OF" RDNs, which means one or // more and order matters. We scan them in order, which // conventionally is big-endian. // DerValue nameseq[] = in.getSequence(5); int i; if (nameseq.length != 0) { names = new RDN[nameseq.length]; } else { clear(); } for (i = 0; i < nameseq.length; i++) names[i] = new RDN(nameseq[i]); } /** * Encodes the name in DER-encoded form. * * @param out where to put the DER-encoded X.500 name */ @Override public void encode(DerOutputStream out) throws IOException { DerOutputStream tmp = new DerOutputStream(); int i; int len = 0; if (names == null) { len = 0; } else { len = names.length; } for (i = 0; i < len; i++) names[i].encode(tmp); out.write(DerValue.tag_Sequence, tmp); } /** * Gets the name in DER-encoded form. * * @return the DER encoded byte array of this name, * null if no names are present. */ public byte[] getEncoded() throws IOException { try (DerOutputStream out = new DerOutputStream()) { DerOutputStream tmp = new DerOutputStream(); int len = 0; if (names == null) { len = 0; } else { len = names.length; } for (int i = 0; i < len; i++) names[i].encode(tmp); out.write(DerValue.tag_Sequence, tmp); return out.toByteArray(); } } /* * Dump the printable form of a distinguished name. Each relative * name is separated from the next by a ",", and assertions in the * relative names have "label=value" syntax. * * Uses RFC 1779 syntax (i.e. little-endian, comma separators) * */ private void generateDN(LdapDNStrConverter ldapDNStrConverter) throws IOException { if (names == null) return; dn = ldapDNStrConverter.encodeDN(this); } private class RDNEnumerator implements Enumeration { private int index; public RDNEnumerator() { index = 0; } @Override public boolean hasMoreElements() { return (index < names.length); } @Override public RDN nextElement() { if (index >= names.length) return null; return names[index++]; } } /****************************************************************/ /* * Maybe return a preallocated OID, to reduce storage costs * and speed recognition of common X.500 attributes. */ static ObjectIdentifier intern(ObjectIdentifier oid) throws IOException { return X500NameAttrMap.getDefault().getOid(oid); } /* * Selected OIDs from X.520 */ /** OID for the "CN=" attribute, denoting a person's common name. */ public static final ObjectIdentifier commonName_oid = X500NameAttrMap.getDefault().getOid("CN"); /** OID for the "UID=" attribute, denoting a person's ID. */ public static final ObjectIdentifier uidName_oid = X500NameAttrMap.getDefault().getOid("UID"); /** OID for the "C=" attribute, denoting a country. */ public static final ObjectIdentifier countryName_oid = X500NameAttrMap.getDefault().getOid("C"); /** OID for the "L=" attribute, denoting a locality (such as a city) */ public static final ObjectIdentifier localityName_oid = X500NameAttrMap.getDefault().getOid("L"); /** OID for the "O=" attribute, denoting an organization name */ public static final ObjectIdentifier orgName_oid = X500NameAttrMap.getDefault().getOid("O"); /** OID for the "OU=" attribute, denoting an organizational unit name */ public static final ObjectIdentifier orgUnitName_oid = X500NameAttrMap.getDefault().getOid("OU"); /** OID for the "S=" attribute, denoting a state (such as Delaware) */ public static final ObjectIdentifier stateName_oid = X500NameAttrMap.getDefault().getOid("ST"); /** OID for the "STREET=" attribute, denoting a street address. */ public static final ObjectIdentifier streetAddress_oid = X500NameAttrMap.getDefault().getOid("STREET"); /** OID for the "T=" attribute, denoting a person's title. */ public static final ObjectIdentifier title_oid = X500NameAttrMap.getDefault().getOid("TITLE"); /** OID for the "E=" attribute, denoting a person's email address. */ public static final ObjectIdentifier email_oid = X500NameAttrMap.getDefault().getOid("E"); /* * OIDs from other sources which show up in X.500 names we * expect to deal with often */ private static final int ipAddress_data[] = // SKIP { 1, 3, 6, 1, 4, 1, 42, 2, 11, 2, 1 }; /** OID for "IP=" IP address attributes, used with SKIP. */ public static final ObjectIdentifier ipAddress_oid = new ObjectIdentifier(ipAddress_data); } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/X500NameAttrMap.java000066400000000000000000000313341412550063600275610ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.util.Enumeration; import java.util.Hashtable; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** * Maps an attribute name in an X500 AVA to its OID and a * converter for the attribute type. The converter converts from a string to * its DER encoded attribute value. * For example, "CN" maps to its OID of * 2.5.4.3 and the Directory String Converter. The Directory String * Converter converts from a string to a DerValue with tag Printable, T.61 or * UniversalString. * * @author Lily Hsiao, Slava Galperin at Netscape Communications, Inc. * */ public class X500NameAttrMap { // // public constructors. // /** * Construct a X500NameAttrMap. */ public X500NameAttrMap() { } // // public get methods. // /** * Get the attribute name (keyword) of the specified OID. * * @param oid An ObjectIdentifier * * @return An attribute name (keyword string) for the OID. */ public String getName(ObjectIdentifier oid) { // XXX assert oid != null return oid2Name.get(oid); } /** * Get the ObjectIdentifier of the attribute name. * * @param name An attribute name (string of ascii characters) * * @return An ObjectIdentifier for the attribute. */ public ObjectIdentifier getOid(String name) { // XXX assert name != null return name2OID.get(name.toUpperCase()); } /** * Get the Attribute Value Converter for the specified attribute name. * * @param name An attribute name * * @return An attribute value converter for the attribute name */ public AVAValueConverter getValueConverter(String name) { ObjectIdentifier oid = name2OID.get(name.toUpperCase()); if (oid == null) return null; return oid2ValueConverter.get(oid); } /** * Get the Attribute Value Converter for the specified ObjectIdentifier. * * @param oid An ObjectIdentifier * * @return An AVAValueConverter for the OID. */ public AVAValueConverter getValueConverter(ObjectIdentifier oid) { return oid2ValueConverter.get(oid); } /** * Get an Enumeration of all attribute names in this map. * * @return An Enumeration of all attribute names. */ public Enumeration getAllNames() { return name2OID.keys(); } /** * Get an Enumeration of all ObjectIdentifiers in this map. * * @return An Enumeration of all OIDs in this map. */ public Enumeration getAllOIDs() { return oid2Name.keys(); } /** * Get the ObjectIdentifier object in the map for the specified OID. * * @param oid An ObjectIdentifier. * @return The ObjectIdentifier object in this map for the OID. */ public ObjectIdentifier getOid(ObjectIdentifier oid) { String name = oid2Name.get(oid); if (name == null) return null; return name2OID.get(name); } // // public add methods. // /** * Adds a attribute name, ObjectIdentifier, AVAValueConverter entry * to the map. * * @param name An attribute name (string of ascii chars) * @param oid The ObjectIdentifier for the attribute. * @param valueConverter An AVAValueConverter object for converting * an value for this attribute from a string to * a DerValue and vice versa. */ public void addNameOID(String name, ObjectIdentifier oid, AVAValueConverter valueConverter) { // normalize name for case insensitive compare. ObjectIdentifier theOid; Class expValueConverter; theOid = name2OID.get(name); if (theOid != null) { expValueConverter = oid2ValueConverter.get(theOid).getClass(); if (!theOid.equals(oid) || expValueConverter != valueConverter.getClass()) { throw new IllegalArgumentException( "Another keyword-oid-valueConverter triple already " + "exists in the X500NameAttrMap "); } return; } name2OID.put(name.toUpperCase(), oid); oid2Name.put(oid, name.toUpperCase()); oid2ValueConverter.put(oid, valueConverter); } // // public static methods. // /** * Get the global default X500NameAttrMap. * * @return The global default X500NameAttrMap. */ public static X500NameAttrMap getDefault() { return defMap; } /** * Get the global default X500NamAttrMap using the DirStrConverter. * * @return The global default X500NameAttrMap using the DirStrConverter. */ public static X500NameAttrMap getDirDefault() { return defDirMap; } /** * Set the global default X500NameAttrMap. * * @param newDefault The new default X500NameAttrMap. */ public static void setDefault(X500NameAttrMap newDefault) { // XXX assert newDef != null defMap = newDefault; } // // private variables // Hashtable name2OID = new Hashtable(); Hashtable oid2Name = new Hashtable(); Hashtable oid2ValueConverter = new Hashtable(); // // global defaults. // private static X500NameAttrMap defMap; private static X500NameAttrMap defDirMap; /* * Create the default maps on initialization. */ static { defMap = new X500NameAttrMap(); AVAValueConverter directoryStr = new DirStrConverter(), ia5Str = new IA5StringConverter(); defMap.addNameOID("CN", new ObjectIdentifier("2.5.4.3"), directoryStr); defMap.addNameOID("OU", new ObjectIdentifier("2.5.4.11"), directoryStr); defMap.addNameOID("O", new ObjectIdentifier("2.5.4.10"), directoryStr); // serialNumber added for CEP support defMap.addNameOID("SERIALNUMBER", new ObjectIdentifier("2.5.4.5"), new PrintableConverter()); defMap.addNameOID("C", new ObjectIdentifier("2.5.4.6"), new PrintableConverter()); defMap.addNameOID("L", new ObjectIdentifier("2.5.4.7"), directoryStr); defMap.addNameOID("ST", new ObjectIdentifier("2.5.4.8"), directoryStr); defMap.addNameOID("STREET", new ObjectIdentifier("2.5.4.9"), directoryStr); defMap.addNameOID("TITLE", new ObjectIdentifier("2.5.4.12"), directoryStr); // RFC 1274 UserId, rfc822MailBox defMap.addNameOID("UID", new ObjectIdentifier("0.9.2342.19200300.100.1.1"), directoryStr); defMap.addNameOID("MAIL", new ObjectIdentifier("0.9.2342.19200300.100.1.3"), ia5Str); // PKCS9 e-mail address defMap.addNameOID("E", new ObjectIdentifier("1.2.840.113549.1.9.1"), ia5Str); // DC definition from draft-ietf-asid-ldap-domains-02.txt defMap.addNameOID("DC", new ObjectIdentifier("0.9.2342.19200300.100.1.25"), ia5Str); // more defined in RFC2459 used in Subject Directory Attr extension defMap.addNameOID("SN", // surname new ObjectIdentifier("2.5.4.4"), directoryStr); defMap.addNameOID("GIVENNAME", new ObjectIdentifier("2.5.4.42"), directoryStr); defMap.addNameOID("INITIALS", new ObjectIdentifier("2.5.4.43"), directoryStr); defMap.addNameOID("GENERATIONQUALIFIER", new ObjectIdentifier("2.5.4.44"), directoryStr); defMap.addNameOID("DNQUALIFIER", new ObjectIdentifier("2.5.4.46"), directoryStr); // these two added mainly for CEP support // PKCS9 unstructured name defMap.addNameOID("UNSTRUCTUREDNAME", new ObjectIdentifier("1.2.840.113549.1.9.2"), ia5Str); // PKCS9 unstructured address defMap.addNameOID("UNSTRUCTUREDADDRESS", new ObjectIdentifier("1.2.840.113549.1.9.8"), new PrintableConverter()); }; static { defDirMap = new X500NameAttrMap(); AVAValueConverter directoryStr = new DirStrConverter(); defDirMap.addNameOID("CN", new ObjectIdentifier("2.5.4.3"), directoryStr); defDirMap.addNameOID("OU", new ObjectIdentifier("2.5.4.11"), directoryStr); defDirMap.addNameOID("O", new ObjectIdentifier("2.5.4.10"), directoryStr); // serialNumber added for CEP support defDirMap.addNameOID("SERIALNUMBER", new ObjectIdentifier("2.5.4.5"), directoryStr); defDirMap.addNameOID("C", new ObjectIdentifier("2.5.4.6"), directoryStr); defDirMap.addNameOID("L", new ObjectIdentifier("2.5.4.7"), directoryStr); defDirMap.addNameOID("ST", new ObjectIdentifier("2.5.4.8"), directoryStr); defDirMap.addNameOID("STREET", new ObjectIdentifier("2.5.4.9"), directoryStr); defDirMap.addNameOID("TITLE", new ObjectIdentifier("2.5.4.12"), directoryStr); // RFC 1274 UserId, rfc822MailBox defDirMap.addNameOID("UID", new ObjectIdentifier("0.9.2342.19200300.100.1.1"), directoryStr); defDirMap.addNameOID("MAIL", new ObjectIdentifier("0.9.2342.19200300.100.1.3"), directoryStr); // PKCS9 e-mail address defDirMap.addNameOID("E", new ObjectIdentifier("1.2.840.113549.1.9.1"), directoryStr); // DC definition from draft-ietf-asid-ldap-domains-02.txt defDirMap.addNameOID("DC", new ObjectIdentifier("0.9.2342.19200300.100.1.25"), directoryStr); // more defined in RFC2459 used in Subject Directory Attr extension defDirMap.addNameOID("SN", // surname new ObjectIdentifier("2.5.4.4"), directoryStr); defDirMap.addNameOID("GIVENNAME", new ObjectIdentifier("2.5.4.42"), directoryStr); defDirMap.addNameOID("INITIALS", new ObjectIdentifier("2.5.4.43"), directoryStr); defDirMap.addNameOID("GENERATIONQUALIFIER", new ObjectIdentifier("2.5.4.44"), directoryStr); defDirMap.addNameOID("DNQUALIFIER", new ObjectIdentifier("2.5.4.46"), directoryStr); // these two added mainly for CEP support // PKCS9 unstructured name defDirMap.addNameOID("UNSTRUCTUREDNAME", new ObjectIdentifier("1.2.840.113549.1.9.2"), directoryStr); // PKCS9 unstructured address defDirMap.addNameOID("UNSTRUCTUREDADDRESS", new ObjectIdentifier("1.2.840.113549.1.9.8"), directoryStr); }; } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/X500Signer.java000066400000000000000000000066671412550063600266520ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.security.NoSuchAlgorithmException; import java.security.Signature; import java.security.SignatureException; /** * This class provides a binding between a Signature object and an * authenticated X.500 name (from an X.509 certificate chain), which * is needed in many public key signing applications. * *

* The name of the signer is important, both because knowing it is the whole point of the signature, and because the * associated X.509 certificate is always used to verify the signature. * *

* The X.509 certificate chain is temporarily not associated with * the signer, but this omission will be resolved. * * @version 1.18 * * @author David Brownell * @author Amit Kapoor * @author Hemma Prafullchandra */ public final class X500Signer { private Signature sig; private X500Name agent; // XXX should be X509CertChain private AlgorithmId algid; /** * Called for each chunk of the data being signed. That * is, you can present the data in many chunks, so that * it doesn't need to be in a single sequential buffer. * * @param buf buffer holding the next chunk of the data to be signed * @param offset starting point of to-be-signed data * @param len how many bytes of data are to be signed * @exception SignatureException on errors. */ public void update(byte buf[], int offset, int len) throws SignatureException { sig.update(buf, offset, len); } /** * Produces the signature for the data processed by update(). * * @exception SignatureException on errors. */ public byte[] sign() throws SignatureException { return sig.sign(); } /** * Returns the algorithm used to sign. */ public AlgorithmId getAlgorithmId() { return algid; } /** * Returns the name of the signing agent. */ public X500Name getSigner() { return agent; } /* * Constructs a binding between a signature and an X500 name * from an X.509 certificate. */ // package private ----hmmmmm ????? public X500Signer(Signature sig, X500Name agent) { if (sig == null || agent == null) throw new IllegalArgumentException("null parameter"); this.sig = sig; this.agent = agent; try { String alg = sig.getAlgorithm(); if (alg.equals("DSA")) { alg = "SHA1withDSA"; } this.algid = AlgorithmId.get(alg); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("internal error! " + e.getMessage()); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/X509AttributeName.java000066400000000000000000000034621412550063600301660ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; /** * This class is used to parse attribute names like "x509.info.extensions". * * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.4 */ public class X509AttributeName { // Public members private static final char SEPARATOR = '.'; // Private data members private String prefix = null; private String suffix = null; /** * Default constructor for the class. Name is of the form * "x509.info.extensions". * * @param name the attribute name. */ public X509AttributeName(String name) { int i = name.indexOf(SEPARATOR); if (i == (-1)) { prefix = name; } else { prefix = name.substring(0, i); suffix = name.substring(i + 1); } } /** * Return the prefix of the name. */ public String getPrefix() { return (prefix); } /** * Return the suffix of the name. */ public String getSuffix() { return (suffix); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/X509CRLImpl.java000066400000000000000000001137221412550063600266650ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Principal; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.security.cert.CRLException; import java.security.cert.Certificate; import java.security.cert.X509CRL; import java.security.cert.X509CRLEntry; import java.security.cert.X509Certificate; import java.util.Date; import java.util.Enumeration; import java.util.Hashtable; import java.util.LinkedHashSet; import java.util.Set; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** *

* An implmentation for X509 CRL (Certificate Revocation List). *

* The X.509 v2 CRL format is described below in ASN.1: * *

 * 
*

* CertificateList ::= SEQUENCE { tbsCertList TBSCertList, signatureAlgorithm AlgorithmIdentifier, signature BIT STRING * } *

* A good description and profiling is provided in the IETF PKIX WG draft, Part I: X.509 Certificate and CRL Profile, * <draft-ietf-pkix-ipki-part1-06.txt>. *

* The ASN.1 definition of tbsCertList is: * *

 * TBSCertList  ::=  SEQUENCE  {
 *     version                 Version OPTIONAL,
 *                             -- if present, must be v2
 *     signature               AlgorithmIdentifier,
 *     issuer                  Name,
 *     thisUpdate              ChoiceOfTime,
 *     nextUpdate              ChoiceOfTime OPTIONAL,
 *     revokedCertificates     SEQUENCE OF SEQUENCE  {
 *         userCertificate         CertificateSerialNumber,
 *         revocationDate          ChoiceOfTime,
 *         crlEntryExtensions      Extensions OPTIONAL
 *                                 -- if present, must be v2
 *         }  OPTIONAL,
 *     crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
 *                                  -- if present, must be v2
 *     }
 * 
* * @author Hemma Prafullchandra * @version 1.8 * @see X509CRL */ public class X509CRLImpl extends X509CRL { // CRL data, and its envelope private byte[] signedCRL = null; // DER encoded crl private byte[] signature = null; // raw signature bits private byte[] tbsCertList = null; // DER encoded "to-be-signed" CRL private AlgorithmId sigAlgId; // sig alg in CRL // crl information private int version; private AlgorithmId infoSigAlgId; // sig alg in "to-be-signed" crl private X500Name issuer; private Date thisUpdate = null; private Date nextUpdate = null; // private static final Hashtable revokedCerts = new Hashtable(); private Hashtable revokedCerts = new Hashtable(); // private static CRLExtensions extensions = null; private CRLExtensions extensions = null; private boolean entriesIncluded = true; private final static boolean isExplicit = true; private boolean readOnly = false; /** * Unmarshals an X.509 CRL from its encoded form, parsing the encoded * bytes. This form of constructor is used by agents which * need to examine and use CRL contents. Note that the buffer * must include only one CRL, and no "garbage" may be left at * the end. * * @param crlData the encoded bytes, with no trailing padding. * @exception CRLException on parsing errors. * @exception X509ExtensionException on extension handling errors. */ public X509CRLImpl(byte[] crlData) throws CRLException, X509ExtensionException { try { DerValue in = new DerValue(crlData); parse(in); signedCRL = crlData; } catch (IOException e) { throw new CRLException("Parsing error: " + e.getMessage()); } } public X509CRLImpl(byte[] crlData, boolean includeEntries) throws CRLException, X509ExtensionException { try { entriesIncluded = includeEntries; DerValue in = new DerValue(crlData); parse(in, includeEntries); signedCRL = crlData; } catch (IOException e) { throw new CRLException("Parsing error: " + e.getMessage()); } } /** * Unmarshals an X.509 CRL from an input stream. Only one CRL * is expected at the end of the input stream. * * @param inStrm an input stream holding at least one CRL * @exception CRLException on parsing errors. * @exception X509ExtensionException on extension handling errors. */ public X509CRLImpl(InputStream inStrm) throws CRLException, X509ExtensionException { try { DerValue val = new DerValue(inStrm); parse(val); signedCRL = val.toByteArray(); } catch (IOException e) { throw new CRLException("Parsing error: " + e.getMessage()); } } /** * Initial CRL constructor, no revoked certs, and no extensions. * * @param issuer the name of the CA issuing this CRL. * @param thisDate the Date of this issue. * @param nextDate the Date of the next CRL. */ public X509CRLImpl(X500Name issuer, Date thisDate, Date nextDate) { this.issuer = issuer; this.thisUpdate = thisDate; this.nextUpdate = nextDate; } /** * CRL constructor, revoked certs, no extensions. * * @param issuer the name of the CA issuing this CRL. * @param thisDate the Date of this issue. * @param nextDate the Date of the next CRL. * @param badCerts the array of revoked certificates. * * @exception CRLException on parsing/construction errors. * @exception X509ExtensionException on extension handling errors. */ public X509CRLImpl(X500Name issuer, Date thisDate, Date nextDate, RevokedCertificate[] badCerts) throws CRLException, X509ExtensionException { this.issuer = issuer; this.thisUpdate = thisDate; this.nextUpdate = nextDate; if (badCerts != null) { for (int i = 0; i < badCerts.length; i++) this.revokedCerts.put(badCerts[i].getSerialNumber(), badCerts[i]); } } /** * CRL constructor, revoked certs and extensions. * * @param issuer the name of the CA issuing this CRL. * @param thisDate the Date of this issue. * @param nextDate the Date of the next CRL. * @param badCerts the array of revoked certificates. * @param crlExts the CRL extensions. * * @exception CRLException on parsing/construction errors. * @exception X509ExtensionException on extension handling errors. */ public X509CRLImpl(X500Name issuer, Date thisDate, Date nextDate, RevokedCertificate[] badCerts, CRLExtensions crlExts) throws CRLException, X509ExtensionException { this.issuer = issuer; this.thisUpdate = thisDate; this.nextUpdate = nextDate; if (badCerts != null) { for (int i = 0; i < badCerts.length; i++) { if (badCerts[i] != null) { this.revokedCerts.put(badCerts[i].getSerialNumber(), badCerts[i]); if (badCerts[i].hasExtensions()) this.version = 1; } } } if (crlExts != null) { this.extensions = crlExts; this.version = 1; } } /** * CRL constructor, revoked certs and extensions. * This will be used by code that constructs CRL and uses * encodeInfo() in order to sign it using external means * (other than sign() method) * * @param issuer the name of the CA issuing this CRL. * @param algId signing algorithm id * @param thisDate the Date of this issue. * @param nextDate the Date of the next CRL. * @param badCerts the array of revoked certificates. * @param crlExts the CRL extensions. */ public X509CRLImpl(X500Name issuer, AlgorithmId algId, Date thisDate, Date nextDate, RevokedCertificate[] badCerts, CRLExtensions crlExts) throws CRLException, X509ExtensionException { this(issuer, thisDate, nextDate, badCerts, crlExts); infoSigAlgId = algId; } /** * CRL constructor, revoked certs and extensions. * * @param issuer the name of the CA issuing this CRL. * @param algId signing algorithm id * @param thisDate the Date of this issue. * @param nextDate the Date of the next CRL. * @param badCerts the hashtable of revoked certificates. * @param crlExts the CRL extensions. * * @exception CRLException on parsing/construction errors. * @exception X509ExtensionException on extension handling errors. */ public X509CRLImpl(X500Name issuer, AlgorithmId algId, Date thisDate, Date nextDate, Hashtable badCerts, CRLExtensions crlExts) throws CRLException, X509ExtensionException { this.issuer = issuer; this.thisUpdate = thisDate; this.nextUpdate = nextDate; this.revokedCerts = badCerts; if (crlExts != null) { this.extensions = crlExts; this.version = 1; } infoSigAlgId = algId; } /** * Returns the ASN.1 DER encoded form of this CRL. * * @exception CRLException if an encoding error occurs. */ @Override public byte[] getEncoded() throws CRLException { if (signedCRL == null) throw new CRLException("Null CRL to encode"); byte[] dup = new byte[signedCRL.length]; System.arraycopy(signedCRL, 0, dup, 0, dup.length); return dup; } /** * Returns true if signedCRL was set. * * @param crl byte array of containing signed CRL. */ public boolean setSignedCRL(byte[] crl) { boolean done = false; if (tbsCertList != null && signedCRL == null) { signedCRL = new byte[crl.length]; System.arraycopy(crl, 0, signedCRL, 0, signedCRL.length); done = true; } return done; } @Override public boolean hasUnsupportedCriticalExtension() { // XXX NOT IMPLEMENTED return true; } /** * Encodes the "to-be-signed" CRL to the OutputStream. * * @param out the OutputStream to write to. * @exception CRLException on encoding errors. * @exception X509ExtensionException on extension encoding errors. */ public void encodeInfo(OutputStream out) throws CRLException, X509ExtensionException { try (DerOutputStream seq = new DerOutputStream()) { DerOutputStream tmp = new DerOutputStream(); DerOutputStream rCerts = new DerOutputStream(); if (version != 0) // v2 crl encode version tmp.putInteger(new BigInt(version)); infoSigAlgId.encode(tmp); issuer.encode(tmp); // from 2050 should encode GeneralizedTime tmp.putUTCTime(thisUpdate); if (nextUpdate != null) tmp.putUTCTime(nextUpdate); if (!revokedCerts.isEmpty()) { for (Enumeration e = revokedCerts.elements(); e.hasMoreElements();) ((RevokedCertImpl) e.nextElement()).encode(rCerts); tmp.write(DerValue.tag_Sequence, rCerts); } if (extensions != null) extensions.encode(tmp, isExplicit); seq.write(DerValue.tag_Sequence, tmp); tbsCertList = seq.toByteArray(); out.write(tbsCertList); } catch (IOException e) { throw new CRLException("Encoding error: " + e.getMessage()); } } /** * Verifies that this CRL was signed using the * private key that corresponds to the specified public key. * * @param key the PublicKey used to carry out the verification. * * @exception NoSuchAlgorithmException on unsupported signature * algorithms. * @exception InvalidKeyException on incorrect key. * @exception NoSuchProviderException if there's no default provider. * @exception SignatureException on signature errors. * @exception CRLException on encoding errors. */ @Override public void verify(PublicKey key) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { String sigProvider = null; verify(key, sigProvider); } /** * Verifies that this CRL was signed using the * private key that corresponds to the specified public key, * and that the signature verification was computed by * the given provider. * * @param key the PublicKey used to carry out the verification. * @param sigProvider the name of the signature provider. * * @exception NoSuchAlgorithmException on unsupported signature * algorithms. * @exception InvalidKeyException on incorrect key. * @exception NoSuchProviderException on incorrect provider. * @exception SignatureException on signature errors. * @exception CRLException on encoding errors. */ @Override public void verify(PublicKey key, String sigProvider) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { if (signedCRL == null) { throw new CRLException("Uninitialized CRL"); } Signature sigVerf = null; String sigAlg = sigAlgId.getName(); if (sigProvider != null && sigProvider.equals("Mozilla-JSS")) { if (sigAlg.equals("MD5withRSA")) { sigAlg = "MD5/RSA"; } else if (sigAlg.equals("MD2withRSA")) { sigAlg = "MD2/RSA"; } else if (sigAlg.equals("SHA1withRSA")) { sigAlg = "SHA1/RSA"; } else if (sigAlg.equals("SHA1withDSA")) { sigAlg = "SHA1/DSA"; } else if (sigAlg.equals("SHA1withEC")) { sigAlg = "SHA1/EC"; } else if (sigAlg.equals("SHA256withRSA")) { sigAlg = "SHA256/RSA"; } else if (sigAlg.equals("SHA384withRSA")) { sigAlg = "SHA384/RSA"; } else if (sigAlg.equals("SHA512withRSA")) { sigAlg = "SHA512/RSA"; } else if (sigAlg.equals("SHA256withEC")) { sigAlg = "SHA256/EC"; } else if (sigAlg.equals("SHA384withEC")) { sigAlg = "SHA384/EC"; } else if (sigAlg.equals("SHA512withEC")) { sigAlg = "SHA512/EC"; } } sigVerf = Signature.getInstance(sigAlg, sigProvider); sigVerf.initVerify(key); if (tbsCertList == null) throw new CRLException("Uninitialized CRL"); sigVerf.update(tbsCertList, 0, tbsCertList.length); if (!sigVerf.verify(signature)) { throw new CRLException("Signature does not match."); } } /** * Encodes an X.509 CRL, and signs it using the key * passed. * * @param key the private key used for signing. * @param algorithm the name of the signature algorithm used. * * @exception NoSuchAlgorithmException on unsupported signature * algorithms. * @exception InvalidKeyException on incorrect key. * @exception NoSuchProviderException on incorrect provider. * @exception SignatureException on signature errors. * @exception CRLException if any mandatory data was omitted. * @exception X509ExtensionException on any extension errors. */ public void sign(PrivateKey key, String algorithm) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException, X509ExtensionException { sign(key, algorithm, null); } /** * Encodes an X.509 CRL, and signs it using the key * passed. * * @param key the private key used for signing. * @param algorithm the name of the signature algorithm used. * @param provider the name of the provider. * * @exception NoSuchAlgorithmException on unsupported signature * algorithms. * @exception InvalidKeyException on incorrect key. * @exception NoSuchProviderException on incorrect provider. * @exception SignatureException on signature errors. * @exception CRLException if any mandatory data was omitted. * @exception X509ExtensionException on any extension errors. */ public void sign(PrivateKey key, String algorithm, String provider) throws CRLException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException, X509ExtensionException { try (DerOutputStream out = new DerOutputStream()){ if (readOnly) throw new CRLException("cannot over-write existing CRL"); Signature sigEngine = null; if (provider == null) sigEngine = Signature.getInstance(algorithm); else sigEngine = Signature.getInstance(algorithm, provider); sigEngine.initSign(key); // in case the name is reset sigAlgId = AlgorithmId.get(sigEngine.getAlgorithm()); infoSigAlgId = sigAlgId; DerOutputStream tmp = new DerOutputStream(); // encode crl info encodeInfo(tmp); // encode algorithm identifier sigAlgId.encode(tmp); // Create and encode the signature itself. sigEngine.update(tbsCertList, 0, tbsCertList.length); signature = sigEngine.sign(); tmp.putBitString(signature); // Wrap the signed data in a SEQUENCE { data, algorithm, sig } out.write(DerValue.tag_Sequence, tmp); signedCRL = out.toByteArray(); readOnly = true; } catch (IOException e) { throw new CRLException("Error while encoding data: " + e.getMessage()); } } /** * Returns a printable string of this CRL. * * @return value of this CRL in a printable form. */ @Override public String toString() { StringBuffer sb = new StringBuffer("X.509 CRL v" + (version + 1) + "\n" + "Signature Algorithm: " + sigAlgId + ", OID=" + sigAlgId.getOID() + "\n" + "Issuer: " + issuer + "\n" + "\nThis Update: " + thisUpdate + "\n"); if (nextUpdate != null) sb.append("Next Update: " + nextUpdate + "\n"); if (revokedCerts.isEmpty()) sb.append("\nNO certificates have been revoked\n"); else { sb.append("\nRevoked Certificates:\n"); for (Enumeration e = revokedCerts.elements(); e.hasMoreElements();) sb.append(e.nextElement()); } if (extensions != null) { for (int i = 0; i < extensions.size(); i++) { sb.append("\nCRL Extension[" + i + "]: " + extensions.elementAt(i)); } } org.mozilla.jss.netscape.security.util.PrettyPrintFormat pp = new org.mozilla.jss.netscape.security.util.PrettyPrintFormat(" ", 20); String signaturebits = pp.toHexString(signature); sb.append("\nSignature:\n" + signaturebits); return sb.toString(); } /** * Checks whether the given serial number is on this CRL. * * @param serialNumber the number to check for. * @return true if the given serial number is on this CRL, * false otherwise. */ public boolean isRevoked(BigInteger serialNumber) { if (revokedCerts == null || revokedCerts.isEmpty()) return false; return revokedCerts.containsKey(serialNumber); } @Override public boolean isRevoked(Certificate cert) { if (cert == null) return false; if (cert instanceof X509Certificate) { return isRevoked(((X509Certificate) cert).getSerialNumber()); } else { return false; } } /** * Gets the version number from the CRL. * The ASN.1 definition for this is: * *
     * Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
     *             -- v3 does not apply to CRLs but appears for consistency
     *             -- with definition of Version for certs
     * 
* * @return the version number. */ @Override public int getVersion() { return version; } /** * Gets the issuer distinguished name from this CRL. * The issuer name identifies the entity who has signed (and * issued the CRL). The issuer name field contains an * X.500 distinguished name (DN). * The ASN.1 definition for this is: * *
     * issuer    Name
     *
     * Name ::= CHOICE { RDNSequence }
     * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
     * RelativeDistinguishedName ::=
     *     SET OF AttributeValueAssertion
     *
     * AttributeValueAssertion ::= SEQUENCE {
     *                               AttributeType,
     *                               AttributeValue }
     * AttributeType ::= OBJECT IDENTIFIER
     * AttributeValue ::= ANY
     * 
* * The Name describes a hierarchical name composed of attributes, * such as country name, and corresponding values, such as US. * The type of the component AttributeValue is determined by the * AttributeType; in general it will be a directoryString. * A directoryString is usually one of PrintableString, * TeletexString or UniversalString. * * @return the issuer name. */ @Override public Principal getIssuerDN() { return issuer; } /** * Gets the thisUpdate date from the CRL. * The ASN.1 definition for this is: * * @return the thisUpdate date from the CRL. */ @Override public Date getThisUpdate() { return (new Date(thisUpdate.getTime())); } /** * Gets the nextUpdate date from the CRL. * * @return the nextUpdate date from the CRL, or null if * not present. */ @Override public Date getNextUpdate() { if (nextUpdate == null) return null; return (new Date(nextUpdate.getTime())); } /** * Get the revoked certificate from the CRL by the serial * number provided. * * @return the revoked certificate or null if there is * no entry in the CRL marked with the provided serial number. * @see RevokedCertificate */ @Override public X509CRLEntry getRevokedCertificate(BigInteger serialNumber) { if (revokedCerts == null || revokedCerts.isEmpty()) return null; return revokedCerts.get(serialNumber); } /** * Gets all the revoked certificates from the CRL. * A Set of RevokedCertificate. * * @return all the revoked certificates or null if there are * none. * @see RevokedCertificate */ @Override public Set getRevokedCertificates() { if (revokedCerts == null || revokedCerts.isEmpty()) return null; else { Set certSet = new LinkedHashSet(revokedCerts.values()); return certSet; } } @SuppressWarnings("unchecked") public Hashtable getListOfRevokedCertificates() { if (revokedCerts == null) { return null; } else { return (Hashtable) revokedCerts.clone(); } } public int getNumberOfRevokedCertificates() { if (revokedCerts == null) return -1; else return revokedCerts.size(); } /** * Gets the DER encoded CRL information, the tbsCertList from this CRL. * This can be used to verify the signature independently. * * @return the DER encoded CRL information. * @exception CRLException on parsing errors. */ @Override public byte[] getTBSCertList() throws CRLException { if (tbsCertList == null) throw new CRLException("Uninitialized CRL"); byte[] dup = new byte[tbsCertList.length]; System.arraycopy(tbsCertList, 0, dup, 0, dup.length); return dup; } /** * Gets the raw Signature bits from the CRL. * * @return the signature. */ @Override public byte[] getSignature() { if (signature == null) return null; byte[] dup = new byte[signature.length]; System.arraycopy(signature, 0, dup, 0, dup.length); return dup; } /** * Returns true if signature was set. * * @param crlSignature byte array of containing CRL signature. */ public boolean setSignature(byte[] crlSignature) { boolean done = false; if (tbsCertList != null && signature == null) { signature = new byte[crlSignature.length]; System.arraycopy(crlSignature, 0, signature, 0, signature.length); done = true; } return done; } /** * Gets the signature algorithm name for the CRL * signature algorithm. For example, the string "SHA1withDSA". * The ASN.1 definition for this is: * *
     * AlgorithmIdentifier  ::=  SEQUENCE  {
     *     algorithm               OBJECT IDENTIFIER,
     *     parameters              ANY DEFINED BY algorithm OPTIONAL  }
     *                             -- contains a value of the type
     *                             -- registered for use with the
     *                             -- algorithm object identifier value
     * 
* * @return the signature algorithm name. */ @Override public String getSigAlgName() { if (sigAlgId == null) return null; return sigAlgId.getName(); } /** * Gets the signature algorithm OID string from the CRL. * An OID is represented by a set of positive whole number separated * by ".", that means,
* <positive whole number>.<positive whole number>.<...> * For example, the string "1.2.840.10040.4.3" identifies the SHA-1 * with DSA signature algorithm, as per the PKIX part I. * * @return the signature algorithm oid string. */ @Override public String getSigAlgOID() { if (sigAlgId == null) return null; ObjectIdentifier oid = sigAlgId.getOID(); return oid.toString(); } /** * Gets the DER encoded signature algorithm parameters from this * CRL's signature algorithm. In most cases, the signature * algorithm parameters are null, the parameters are usually * supplied with the Public Key. * * @return the DER encoded signature algorithm parameters, or * null if no parameters are present. */ @Override public byte[] getSigAlgParams() { if (sigAlgId == null) return null; try { return sigAlgId.getEncodedParams(); } catch (IOException e) { return null; } } /** * Gets a Set of the extension(s) marked CRITICAL in the * CRL by OID strings. * * @return a set of the extension oid strings in the * CRL that are marked critical. */ @Override public Set getCriticalExtensionOIDs() { if (extensions == null) return null; Set extSet = new LinkedHashSet(); Extension ex; for (Enumeration e = extensions.getElements(); e.hasMoreElements();) { ex = e.nextElement(); if (ex.isCritical()) { extSet.add(ex.getExtensionId().toString()); } } return extSet; } /** * Gets a Set of the extension(s) marked NON-CRITICAL in the * CRL by OID strings. * * @return a set of the extension oid strings in the * CRL that are NOT marked critical. */ @Override public Set getNonCriticalExtensionOIDs() { if (extensions == null) return null; Set extSet = new LinkedHashSet(); Extension ex; for (Enumeration e = extensions.getElements(); e.hasMoreElements();) { ex = e.nextElement(); if (!ex.isCritical()) extSet.add(ex.getExtensionId().toString()); } return extSet; } /** * Gets the DER encoded OCTET string for the extension value * (extnValue) identified by the passed in oid String. * The oid string is * represented by a set of positive whole number separated * by ".", that means,
* <positive whole number>.<positive whole number>.<...> * * @param oid the Object Identifier value for the extension. * @return the der encoded octet string of the extension value. */ @Override public byte[] getExtensionValue(String oid) { if (extensions == null) return null; try (DerOutputStream out = new DerOutputStream()) { String extAlias = OIDMap.getName(new ObjectIdentifier(oid)); Extension crlExt = null; if (extAlias == null) { // may be unknown ObjectIdentifier findOID = new ObjectIdentifier(oid); Extension ex = null; ObjectIdentifier inCertOID; for (Enumeration e = extensions.getElements(); e.hasMoreElements();) { ex = e.nextElement(); inCertOID = ex.getExtensionId(); if (inCertOID.equals(findOID)) { crlExt = ex; break; } } } else crlExt = extensions.get(extAlias); if (crlExt == null) return null; byte[] extData = crlExt.getExtensionValue(); if (extData == null) return null; out.putOctetString(extData); return out.toByteArray(); } catch (Exception e) { return null; } } public BigInteger getCRLNumber() { try { CRLExtensions exts = getExtensions(); if (exts == null) return null; Enumeration e = exts.getElements(); while (e.hasMoreElements()) { Extension ext = e.nextElement(); if (ext instanceof CRLNumberExtension) { CRLNumberExtension numExt = (CRLNumberExtension) ext; return (BigInteger) numExt.get(CRLNumberExtension.NUMBER); } } } catch (Exception e) { } return null; } public BigInteger getDeltaBaseCRLNumber() { try { CRLExtensions exts = getExtensions(); if (exts == null) return null; Enumeration e = exts.getElements(); while (e.hasMoreElements()) { Extension ext = e.nextElement(); if (ext instanceof DeltaCRLIndicatorExtension) { DeltaCRLIndicatorExtension numExt = (DeltaCRLIndicatorExtension) ext; return (BigInteger) numExt.get(DeltaCRLIndicatorExtension.NUMBER); } } } catch (Exception e) { } return null; } public boolean isDeltaCRL() { try { CRLExtensions exts = getExtensions(); if (exts == null) return false; Enumeration e = exts.getElements(); while (e.hasMoreElements()) { Extension ext = e.nextElement(); if (ext instanceof DeltaCRLIndicatorExtension) { return true; } } } catch (Exception e) { } return false; } /** * Returns extensions for this impl. */ public CRLExtensions getExtensions() { return extensions; } public boolean areEntriesIncluded() { return entriesIncluded; } /*********************************************************************/ /* * Parses an X.509 CRL, should be used only by constructors. */ private void parse(DerValue val) throws CRLException, IOException, X509ExtensionException { parse(val, true); } private void parse(DerValue val, boolean includeEntries) throws CRLException, IOException, X509ExtensionException { // check if can over write the certificate if (readOnly) throw new CRLException("cannot over-write existing CRL"); readOnly = true; DerValue seq[] = new DerValue[3]; seq[0] = val.data.getDerValue(); seq[1] = val.data.getDerValue(); seq[2] = val.data.getDerValue(); if (val.data.available() != 0) throw new CRLException("signed overrun, bytes = " + val.data.available()); if (seq[0].tag != DerValue.tag_Sequence) throw new CRLException("signed CRL fields invalid"); sigAlgId = AlgorithmId.parse(seq[1]); signature = seq[2].getBitString(); if (seq[1].data.available() != 0) throw new CRLException("AlgorithmId field overrun"); if (seq[2].data.available() != 0) throw new CRLException("Signature field overrun"); // the tbsCertsList tbsCertList = seq[0].toByteArray(); // parse the information DerInputStream derStrm = seq[0].data; DerValue tmp; byte nextByte; // version (optional if v1) version = 0; // by default, version = v1 == 0 nextByte = (byte) derStrm.peekByte(); if (nextByte == DerValue.tag_Integer) { version = derStrm.getInteger().toInt(); if (version != 1) // i.e. v2 throw new CRLException("Invalid version"); } tmp = derStrm.getDerValue(); // signature { AlgorithmId tmpId = AlgorithmId.parse(tmp); if (!tmpId.equals(sigAlgId)) throw new CRLException("Signature algorithm mismatch"); infoSigAlgId = tmpId; } // issuer issuer = new X500Name(derStrm); // thisUpdate // check if UTCTime encoded or GeneralizedTime nextByte = (byte) derStrm.peekByte(); if (nextByte == DerValue.tag_UtcTime) { thisUpdate = derStrm.getUTCTime(); } else if (nextByte == DerValue.tag_GeneralizedTime) { thisUpdate = derStrm.getGeneralizedTime(); } else { throw new CRLException("Invalid encoding for thisUpdate" + " (tag=" + nextByte + ")"); } if (derStrm.available() == 0) return; // done parsing no more optional fields present // nextUpdate (optional) nextByte = (byte) derStrm.peekByte(); if (nextByte == DerValue.tag_UtcTime) { nextUpdate = derStrm.getUTCTime(); } else if (nextByte == DerValue.tag_GeneralizedTime) { nextUpdate = derStrm.getGeneralizedTime(); } // else it is not present if (derStrm.available() == 0) return; // done parsing no more optional fields present // revokedCertificates (optional) nextByte = (byte) derStrm.peekByte(); if ((nextByte == DerValue.tag_SequenceOf) && (!((nextByte & 0x0c0) == 0x080))) { if (includeEntries) { DerValue[] badCerts = derStrm.getSequence(4); for (int i = 0; i < badCerts.length; i++) { RevokedCertImpl entry = new RevokedCertImpl(badCerts[i]); if (entry.hasExtensions() && (version == 0)) throw new CRLException("Invalid encoding, extensions" + " not supported in CRL v1 entries."); revokedCerts.put(entry.getSerialNumber(), entry); } } else { derStrm.skipSequence(4); } } if (derStrm.available() == 0) return; // done parsing no extensions // crlExtensions (optional) tmp = derStrm.getDerValue(); if (tmp.isConstructed() && tmp.isContextSpecific((byte) 0)) { if (version == 0) throw new CRLException("Invalid encoding, extensions not" + " supported in CRL v1."); extensions = new CRLExtensions(tmp.data); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/X509CertImpl.java000066400000000000000000001271001412550063600271350ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Principal; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.SignatureException; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateFactory; import java.security.cert.CertificateNotYetValidException; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; import java.util.Date; import java.util.Enumeration; import java.util.LinkedHashSet; import java.util.Set; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerEncoder; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** * The X509CertImpl class represents an X.509 certificate. These certificates * are widely used to support authentication and other functionality in * Internet security systems. Common applications include Privacy Enhanced * Mail (PEM), Transport Layer Security (SSL), code signing for trusted * software distribution, and Secure Electronic Transactions (SET). There * is a commercial infrastructure ready to manage large scale deployments * of X.509 identity certificates. * *

* These certificates are managed and vouched for by Certificate * Authorities (CAs). CAs are services which create certificates by placing data in the X.509 standard format and * then digitally signing that data. Such signatures are quite difficult to forge. CAs act as trusted third parties, * making introductions between agents who have no direct knowledge of each other. CA certificates are either signed by * themselves, or by some other CA such as a "root" CA. * *

* RFC 1422 is very informative, though it does not describe much of the recent work being done with X.509 certificates. * That includes a 1996 version (X.509v3) and a variety of enhancements being made to facilitate an explosion of * personal certificates used as "Internet Drivers' Licences", or with SET for credit card transactions. * *

* More recent work includes the IETF PKIX Working Group efforts, especially part 1. * * @author Dave Brownell * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.94 97/12/10 * @see X509CertInfo */ public class X509CertImpl extends X509Certificate implements DerEncoder { // Serialization compatibility with the X509CertImpl in x509v1.jar // supporting the subset of X509Certificate on JDK1.1.x platforms. static final long serialVersionUID = -2048442350420423405L; private static final String DOT = "."; /** * Public attribute names. */ public static final String NAME = "x509"; public static final String INFO = X509CertInfo.NAME; public static final String ALG_ID = "algorithm"; public static final String SIGNATURE = "signature"; public static final String SIGNED_CERT = "signed_cert"; /** * The following are defined for ease-of-use. These * are the most frequently retrieved attributes. */ // x509.info.subject.dname public static final String SUBJECT_DN = NAME + DOT + INFO + DOT + X509CertInfo.SUBJECT + DOT + CertificateSubjectName.DN_NAME; // x509.info.issuer.dname public static final String ISSUER_DN = NAME + DOT + INFO + DOT + X509CertInfo.ISSUER + DOT + CertificateIssuerName.DN_NAME; // x509.info.serialNumber.number public static final String SERIAL_ID = NAME + DOT + INFO + DOT + X509CertInfo.SERIAL_NUMBER + DOT + CertificateSerialNumber.NUMBER; // x509.info.key.value public static final String PUBLIC_KEY = NAME + DOT + INFO + DOT + X509CertInfo.KEY + DOT + CertificateX509Key.KEY; // x509.algorithm public static final String SIG_ALG = NAME + DOT + ALG_ID; // x509.signature public static final String SIG = NAME + DOT + SIGNATURE; // when we sign and decode we set this to true // this is our means to make certificates immutable private boolean readOnly = false; // Certificate data, and its envelope private byte[] signedCert; protected X509CertInfo info = null; protected AlgorithmId algId; protected byte[] signature; // recognized extension OIDS private static final String KEY_USAGE_OID = "2.5.29.15"; private static final String BASIC_CONSTRAINT_OID = "2.5.29.19"; /** * Default constructor. */ public X509CertImpl() { } /** * Unmarshals a certificate from its encoded form, parsing the * encoded bytes. This form of constructor is used by agents which * need to examine and use certificate contents. That is, this is * one of the more commonly used constructors. Note that the buffer * must include only a certificate, and no "garbage" may be left at * the end. If you need to ignore data at the end of a certificate, * use another constructor. * * @param certData the encoded bytes, with no trailing padding. * @exception CertificateException on parsing and initialization errors. */ public X509CertImpl(byte[] certData) throws CertificateException { this(certData, null); } /** * As a special optimization, this constructor acts as X509CertImpl(byte[]) * except that it takes an X509CertInfo which it uses as a 'hint' for * how to construct one field. * * @param certData the encode bytes, with no traiing padding * @param certInfo the certInfo which has already been constructed * from the certData */ public X509CertImpl(byte[] certData, X509CertInfo certInfo) throws CertificateException { // setting info here causes it to skip decoding in the parse() // method info = certInfo; try { DerValue in = new DerValue(certData); parse(in); signedCert = certData; } catch (IOException e) { throw new CertificateException("Unable to parse certificate data: " + e.getMessage(), e); } } /** * unmarshals an X.509 certificate from an input stream. * * @param in an input stream holding at least one certificate * @exception CertificateException on parsing and initialization errors. */ public X509CertImpl(InputStream in) throws CertificateException { try { DerValue val = new DerValue(in); parse(val); signedCert = val.toByteArray(); } catch (IOException e) { throw new CertificateException("Unable to parse certificate data: " + e.getMessage(), e); } } /** * Construct an initialized X509 Certificate. The certificate is stored * in raw form and has to be signed to be useful. * * @param certInfo the X509CertificateInfo which the Certificate is to be * created from. */ public X509CertImpl(X509CertInfo certInfo) { this.info = certInfo; } /** * Unmarshal a certificate from its encoded form, parsing a DER value. * This form of constructor is used by agents which need to examine * and use certificate contents. * * @param derVal the der value containing the encoded cert. * @exception CertificateException on parsing and initialization errors. */ public X509CertImpl(DerValue derVal) throws CertificateException { try { parse(derVal); signedCert = derVal.toByteArray(); } catch (IOException e) { throw new CertificateException("Unable to parse certificate data: " + e.getMessage(), e); } } @Override public boolean hasUnsupportedCriticalExtension() { // XXX NOT IMPLEMENTED return true; } /** * Decode an X.509 certificate from an input stream. * * @param in an input stream holding at least one certificate * @exception CertificateException on parsing errors. * @exception IOException on other errors. */ public void decode(InputStream in) throws CertificateException, IOException { DerValue val = new DerValue(in); parse(val); signedCert = val.toByteArray(); } /** * Appends the certificate to an output stream. * * @param out an input stream to which the certificate is appended. * @exception CertificateEncodingException on encoding errors. */ public void encode(OutputStream out) throws CertificateEncodingException { if (signedCert == null) throw new CertificateEncodingException( "Missing certificate to encode"); try { out.write(signedCert); } catch (IOException e) { throw new CertificateEncodingException("Unable to encode certificate: " + e.getMessage(), e); } } /** * DER encode this object onto an output stream. * Implements the DerEncoder interface. * * @param out * the output stream on which to write the DER encoding. * * @exception IOException on encoding error. */ @Override public void derEncode(OutputStream out) throws IOException { if (signedCert == null) throw new IOException("Missing certificate to encode"); out.write(signedCert); } /** * Returns the encoded form of this certificate. It is * assumed that each certificate type would have only a single * form of encoding; for example, X.509 certificates would * be encoded as ASN.1 DER. * * @exception CertificateEncodingException if an encoding error occurs. */ @Override public byte[] getEncoded() throws CertificateEncodingException { if (signedCert == null) throw new CertificateEncodingException( "Missing certificate to encode"); byte[] dup = new byte[signedCert.length]; System.arraycopy(signedCert, 0, dup, 0, dup.length); return dup; } /** * Throws an exception if the certificate was not signed using the * verification key provided. Successfully verifying a certificate * does not indicate that one should trust the entity which * it represents. * * @param key the public key used for verification. * * @exception InvalidKeyException on incorrect key. * @exception NoSuchAlgorithmException on unsupported signature * algorithms. * @exception NoSuchProviderException if there's no default provider. * @exception SignatureException on signature errors. * @exception CertificateException on encoding errors. */ @Override public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { String sigProvider = null; verify(key, sigProvider); } /** * Throws an exception if the certificate was not signed using the * verification key provided. Successfully verifying a certificate * does not indicate that one should trust the entity which * it represents. * * @param key the public key used for verification. * @param sigProvider the name of the provider. * * @exception NoSuchAlgorithmException on unsupported signature * algorithms. * @exception InvalidKeyException on incorrect key. * @exception NoSuchProviderException on incorrect provider. * @exception SignatureException on signature errors. * @exception CertificateException on encoding errors. */ @Override public void verify(PublicKey key, String sigProvider) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { if (signedCert == null) { throw new CertificateEncodingException("Missing certificate"); } // Verify the signature ... Signature sigVerf = null; sigVerf = Signature.getInstance(algId.getName(), sigProvider); sigVerf.initVerify(key); byte[] rawCert = info.getEncodedInfo(); sigVerf.update(rawCert, 0, rawCert.length); if (!sigVerf.verify(signature)) { throw new SignatureException("Signature does not match"); } } /** * Creates an X.509 certificate, and signs it using the key * passed (associating a signature algorithm and an X.500 name). * This operation is used to implement the certificate generation * functionality of a certificate authority. * * @param key the private key used for signing. * @param algorithm the name of the signature algorithm used. * * @exception InvalidKeyException on incorrect key. * @exception NoSuchAlgorithmException on unsupported signature * algorithms. * @exception NoSuchProviderException if there's no default provider. * @exception SignatureException on signature errors. * @exception CertificateException on encoding errors. */ public void sign(PrivateKey key, String algorithm) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { sign(key, algorithm, null); } /** * Creates an X.509 certificate, and signs it using the key * passed (associating a signature algorithm and an X.500 name). * This operation is used to implement the certificate generation * functionality of a certificate authority. * * @param key the private key used for signing. * @param algorithm the name of the signature algorithm used. * @param provider the name of the provider. * * @exception NoSuchAlgorithmException on unsupported signature * algorithms. * @exception InvalidKeyException on incorrect key. * @exception NoSuchProviderException on incorrect provider. * @exception SignatureException on signature errors. * @exception CertificateException on encoding errors. */ public void sign(PrivateKey key, String algorithm, String provider) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { try (DerOutputStream out = new DerOutputStream()){ if (readOnly) throw new CertificateEncodingException( "Cannot overwrite existing certificate"); Signature sigEngine = null; if (provider == null) sigEngine = Signature.getInstance(algorithm); else sigEngine = Signature.getInstance(algorithm, provider); sigEngine.initSign(key); // in case the name is reset algId = AlgorithmId.get(sigEngine.getAlgorithm()); DerOutputStream tmp = new DerOutputStream(); // encode certificate info info.encode(tmp); byte[] rawCert = tmp.toByteArray(); // encode algorithm identifier algId.encode(tmp); // Create and encode the signature itself. sigEngine.update(rawCert, 0, rawCert.length); signature = sigEngine.sign(); tmp.putBitString(signature); // Wrap the signed data in a SEQUENCE { data, algorithm, sig } out.write(DerValue.tag_Sequence, tmp); signedCert = out.toByteArray(); readOnly = true; } catch (IOException e) { throw new CertificateEncodingException("Unable to sign certificate: " + e.getMessage(), e); } } /** * Checks that the certificate is currently valid, i.e. the current * time is within the specified validity period. * * @exception CertificateExpiredException if the certificate has expired. * @exception CertificateNotYetValidException if the certificate is not * yet valid. */ @Override public void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException { Date date = new Date(); checkValidity(date); } /** * Checks that the specified date is within the certificate's * validity period, or basically if the certificate would be * valid at the specified date/time. * * @param date the Date to check against to see if this certificate * is valid at that date/time. * * @exception CertificateExpiredException if the certificate has expired * with respect to the date supplied. * @exception CertificateNotYetValidException if the certificate is not * yet valid with respect to the date supplied. */ @Override public void checkValidity(Date date) throws CertificateExpiredException, CertificateNotYetValidException { CertificateValidity interval = null; try { interval = (CertificateValidity) info.get(CertificateValidity.NAME); } catch (Exception e) { throw new CertificateNotYetValidException("Incorrect validity period: " + e.getMessage()); } if (interval == null) throw new CertificateNotYetValidException("Null validity period"); interval.valid(date); } /** * Return the requested attribute from the certificate. * * @param name the name of the attribute. * @exception CertificateParsingException on invalid attribute identifier. */ public Object get(String name) throws CertificateParsingException { X509AttributeName attr = new X509AttributeName(name); String id = attr.getPrefix(); if (!(id.equalsIgnoreCase(NAME))) { throw new CertificateParsingException("Invalid root of " + "attribute name, expected [" + NAME + "], received " + "[" + id + "]"); } attr = new X509AttributeName(attr.getSuffix()); id = attr.getPrefix(); if (id.equalsIgnoreCase(INFO)) { if (attr.getSuffix() != null) { try { return info.get(attr.getSuffix()); } catch (IOException e) { throw new CertificateParsingException("Unable to get certificate attribute: " + e.getMessage(), e); } catch (CertificateException e) { throw new CertificateParsingException("Unable to get certificate attribute: " + e.getMessage(), e); } } else { return (info); } } else if (id.equalsIgnoreCase(ALG_ID)) { return (algId); } else if (id.equalsIgnoreCase(SIGNATURE)) { return (signature); } else if (id.equalsIgnoreCase(SIGNED_CERT)) { return (signedCert); } else { throw new CertificateParsingException("Attribute name not " + "recognized or get() not allowed for the same: " + id); } } /** * Set the requested attribute in the certificate. * * @param name the name of the attribute. * @param obj the value of the attribute. * @exception CertificateException on invalid attribute identifier. * @exception IOException on encoding error of attribute. */ public void set(String name, Object obj) throws CertificateException, IOException { // check if immutable if (readOnly) throw new CertificateException("Cannot overwrite existing certificate"); X509AttributeName attr = new X509AttributeName(name); String id = attr.getPrefix(); if (!(id.equalsIgnoreCase(NAME))) { throw new CertificateException("Invalid root of attribute name," + " expected [" + NAME + "], received " + id); } attr = new X509AttributeName(attr.getSuffix()); id = attr.getPrefix(); if (id.equalsIgnoreCase(INFO)) { if (attr.getSuffix() == null) { if (!(obj instanceof X509CertInfo)) { throw new CertificateException("Attribute value should" + " be of type X509CertInfo."); } info = (X509CertInfo) obj; signedCert = null; //reset this as certificate data has changed } else { info.set(attr.getSuffix(), obj); signedCert = null; //reset this as certificate data has changed } } else { throw new CertificateException("Attribute name not recognized or " + "set() not allowed for the same: " + id); } } /** * Delete the requested attribute from the certificate. * * @param name the name of the attribute. * @exception CertificateException on invalid attribute identifier. * @exception IOException on other errors. */ public void delete(String name) throws CertificateException, IOException { // check if immutable if (readOnly) throw new CertificateException("Cannot overwrite existing certificate"); X509AttributeName attr = new X509AttributeName(name); String id = attr.getPrefix(); if (!(id.equalsIgnoreCase(NAME))) { throw new CertificateException("Invalid root of attribute name," + " expected [" + NAME + "], received " + id); } attr = new X509AttributeName(attr.getSuffix()); id = attr.getPrefix(); if (id.equalsIgnoreCase(INFO)) { if (attr.getSuffix() != null) { info = null; } else { info.delete(attr.getSuffix()); } } else if (id.equalsIgnoreCase(ALG_ID)) { algId = null; } else if (id.equalsIgnoreCase(SIGNATURE)) { signature = null; } else if (id.equalsIgnoreCase(SIGNED_CERT)) { signedCert = null; } else { throw new CertificateException("Attribute name not recognized or " + "delete() not allowed for the same: " + id); } } /** * Return an enumeration of names of attributes existing within this * attribute. */ public Enumeration getElements() { Vector elements = new Vector(); elements.addElement(NAME + DOT + INFO); elements.addElement(NAME + DOT + ALG_ID); elements.addElement(NAME + DOT + SIGNATURE); elements.addElement(NAME + DOT + SIGNED_CERT); return (elements.elements()); } /** * Return the name of this attribute. */ public String getName() { return (NAME); } /** * Returns a printable representation of the certificate. This does not * contain all the information available to distinguish this from any * other certificate. The certificate must be fully constructed * before this function may be called. */ @Override public String toString() { if (info == null || algId == null || signature == null) return ""; StringBuffer sb = new StringBuffer("[\n"+info.toString() + "\n" + " Algorithm: [" + algId.toString() + "]\n"); org.mozilla.jss.netscape.security.util.PrettyPrintFormat pp = new org.mozilla.jss.netscape.security.util.PrettyPrintFormat(" ", 20); String signaturebits = pp.toHexString(signature); sb.append(" Signature:\n" + signaturebits); sb.append("]"); return sb.toString(); } // the strongly typed gets, as per java.security.cert.X509Certificate /** * Gets the publickey from this certificate. * * @return the publickey. */ @Override public PublicKey getPublicKey() { if (info == null) return null; try { PublicKey key = (PublicKey) info.get(CertificateX509Key.NAME + DOT + CertificateX509Key.KEY); return key; } catch (Exception e) { return null; } } /** * Gets the version number from the certificate. * * @return the version number. */ @Override public int getVersion() { if (info == null) return -1; try { int vers = ((Integer) info.get(CertificateVersion.NAME + DOT + CertificateVersion.VERSION)).intValue(); return vers; } catch (Exception e) { return -1; } } /** * Gets the serial number from the certificate. * * @return the serial number. */ @Override public BigInteger getSerialNumber() { if (info == null) return null; try { SerialNumber ser = (SerialNumber) info.get( CertificateSerialNumber.NAME + DOT + CertificateSerialNumber.NUMBER); return ser.getNumber().toBigInteger(); } catch (Exception e) { return null; } } /** * Gets the subject distinguished name from the certificate. * * @return the subject name. */ @Override public Principal getSubjectDN() { if (info == null) return null; try { Principal subject = (Principal) info.get( CertificateSubjectName.NAME + DOT + CertificateSubjectName.DN_NAME); return subject; } catch (Exception e) { return null; } } public CertificateSubjectName getSubjectObj() { return info.getSubjectObj(); } public X509CertInfo getInfo() { return info; } /** * Gets the issuer distinguished name from the certificate. * * @return the issuer name. */ @Override public Principal getIssuerDN() { if (info == null) return null; try { Principal issuer = (Principal) info.get( CertificateIssuerName.NAME + DOT + CertificateIssuerName.DN_NAME); return issuer; } catch (Exception e) { return null; } } public CertificateIssuerName getIssuerObj() { return info.getIssuerObj(); } /** * Gets the notBefore date from the validity period of the certificate. * * @return the start date of the validity period. */ @Override public Date getNotBefore() { if (info == null) return null; try { Date d = (Date) info.get(CertificateValidity.NAME + DOT + CertificateValidity.NOT_BEFORE); return d; } catch (Exception e) { return null; } } /** * Gets the notAfter date from the validity period of the certificate. * * @return the end date of the validity period. */ @Override public Date getNotAfter() { if (info == null) return null; try { Date d = (Date) info.get(CertificateValidity.NAME + DOT + CertificateValidity.NOT_AFTER); return d; } catch (Exception e) { return null; } } /** * Gets the DER encoded certificate informations, the tbsCertificate from this certificate. * This can be used to verify the signature independently. * * @return the DER encoded certificate information. * @exception CertificateEncodingException if an encoding error occurs. */ @Override public byte[] getTBSCertificate() throws CertificateEncodingException { if (info != null) { return info.getEncodedInfo(); } else throw new CertificateEncodingException("Uninitialized certificate"); } /** * Gets the raw Signature bits from the certificate. * * @return the signature. */ @Override public byte[] getSignature() { if (signature == null) return null; byte[] dup = new byte[signature.length]; System.arraycopy(signature, 0, dup, 0, dup.length); return dup; } /** * Gets the signature algorithm name for the certificate * signature algorithm. * For example, the string "SHA-1/DSA" or "DSS". * * @return the signature algorithm name. */ @Override public String getSigAlgName() { if (algId == null) return null; return (algId.getName()); } /** * Gets the signature algorithm OID string from the certificate. * For example, the string "1.2.840.10040.4.3" * * @return the signature algorithm oid string. */ @Override public String getSigAlgOID() { if (algId == null) return null; ObjectIdentifier oid = algId.getOID(); return (oid.toString()); } /** * Gets the DER encoded signature algorithm parameters from this * certificate's signature algorithm. * * @return the DER encoded signature algorithm parameters, or * null if no parameters are present. */ @Override public byte[] getSigAlgParams() { if (algId == null) return null; try { return algId.getEncodedParams(); } catch (IOException e) { return null; } } /** * Gets the Issuer Unique Identity from the certificate. * * @return the Issuer Unique Identity. */ @Override public boolean[] getIssuerUniqueID() { if (info == null) return null; try { UniqueIdentity id = (UniqueIdentity) info.get( CertificateIssuerUniqueIdentity.NAME + DOT + CertificateIssuerUniqueIdentity.ID); if (id == null) return null; else return (id.getId()); } catch (Exception e) { return null; } } /** * Gets the Subject Unique Identity from the certificate. * * @return the Subject Unique Identity. */ @Override public boolean[] getSubjectUniqueID() { if (info == null) return null; try { UniqueIdentity id = (UniqueIdentity) info.get( CertificateSubjectUniqueIdentity.NAME + DOT + CertificateSubjectUniqueIdentity.ID); if (id == null) return null; else return (id.getId()); } catch (Exception e) { return null; } } /** * Gets a Set of the extension(s) marked CRITICAL in the * certificate by OID strings. * * @return a set of the extension oid strings in the * certificate that are marked critical. */ @Override public Set getCriticalExtensionOIDs() { if (info == null) return null; try { CertificateExtensions exts = (CertificateExtensions) info.get( CertificateExtensions.NAME); if (exts == null) return null; Set extSet = new LinkedHashSet(); Extension ex; for (Enumeration e = exts.getAttributes(); e.hasMoreElements();) { ex = e.nextElement(); if (ex.isCritical()) extSet.add(ex.getExtensionId().toString()); } return extSet; } catch (Exception e) { return null; } } /** * Gets a Set of the extension(s) marked NON-CRITICAL in the * certificate by OID strings. * * @return a set of the extension oid strings in the * certificate that are NOT marked critical. */ @Override public Set getNonCriticalExtensionOIDs() { if (info == null) return null; try { CertificateExtensions exts = (CertificateExtensions) info.get( CertificateExtensions.NAME); if (exts == null) return null; Set extSet = new LinkedHashSet(); Extension ex; for (Enumeration e = exts.getAttributes(); e.hasMoreElements();) { ex = e.nextElement(); if (!ex.isCritical()) extSet.add(ex.getExtensionId().toString()); } return extSet; } catch (Exception e) { return null; } } public Extension getExtension(String oid) { try { CertificateExtensions exts = (CertificateExtensions) info.get( CertificateExtensions.NAME); if (exts == null) return null; ObjectIdentifier findOID = new ObjectIdentifier(oid); Extension ex = null; ; ObjectIdentifier inCertOID; for (Enumeration e = exts.getAttributes(); e.hasMoreElements();) { ex = e.nextElement(); inCertOID = ex.getExtensionId(); if (inCertOID.equals(findOID)) { return ex; } } } catch (Exception e) { } return null; } /** * Gets the DER encoded extension identified by the passed * in oid String. * * @param oid the Object Identifier value for the extension. */ @Override public byte[] getExtensionValue(String oid) { DerOutputStream out = null; try { String extAlias = OIDMap.getName(new ObjectIdentifier(oid)); Extension certExt = null; if (extAlias == null) { // may be unknown // get the extensions, search thru' for this oid CertificateExtensions exts = (CertificateExtensions) info.get( CertificateExtensions.NAME); if (exts == null) return null; ObjectIdentifier findOID = new ObjectIdentifier(oid); Extension ex = null; ; ObjectIdentifier inCertOID; for (Enumeration e = exts.getAttributes(); e.hasMoreElements();) { ex = e.nextElement(); inCertOID = ex.getExtensionId(); if (inCertOID.equals(findOID)) { certExt = ex; break; } } } else { // there's sub-class that can handle this extension certExt = (Extension) this.get(extAlias); } if (certExt == null) return null; byte[] extData = certExt.getExtensionValue(); if (extData == null) return null; out = new DerOutputStream(); out.putOctetString(extData); return out.toByteArray(); } catch (Exception e) { return null; } finally { if (out != null) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * Get a boolean array representing the bits of the KeyUsage extension, * (oid = 2.5.29.15). * * @return the bit values of this extension as an array of booleans. */ @Override public boolean[] getKeyUsage() { try { String extAlias = OIDMap.getName(new ObjectIdentifier( KEY_USAGE_OID)); if (extAlias == null) return null; KeyUsageExtension certExt = (KeyUsageExtension) this.get(extAlias); if (certExt == null) return null; return certExt.getBits(); } catch (Exception e) { return null; } } /** * Get the certificate constraints path length from the * the critical BasicConstraints extension, (oid = 2.5.29.19). * * @return the length of the constraint. */ @Override public int getBasicConstraints() { try { String extAlias = OIDMap.getName(new ObjectIdentifier( BASIC_CONSTRAINT_OID)); if (extAlias == null) return -1; BasicConstraintsExtension certExt = (BasicConstraintsExtension) this.get(extAlias); if (certExt == null) return -1; if (((Boolean) certExt.get(BasicConstraintsExtension.IS_CA)).booleanValue() == true) return ((Integer) certExt.get( BasicConstraintsExtension.PATH_LEN)).intValue(); else return -1; } catch (Exception e) { return -1; } } public boolean getBasicConstraintsIsCA() { boolean isCA = false; try { String extAlias = OIDMap.getName(new ObjectIdentifier( BASIC_CONSTRAINT_OID)); if (extAlias == null) return false; BasicConstraintsExtension certExt = (BasicConstraintsExtension) this.get(extAlias); if (certExt == null) return false; isCA = ((Boolean) certExt.get(BasicConstraintsExtension.IS_CA)).booleanValue(); } catch (Exception e) { return false; } return isCA; } /************************************************************/ /* * Cert is a SIGNED ASN.1 macro, a three elment sequence: * * - Data to be signed (ToBeSigned) -- the "raw" cert * - Signature algorithm (SigAlgId) * - The signature bits * * This routine unmarshals the certificate, saving the signature * parts away for later verification. */ private void parse(DerValue val) throws CertificateException, IOException { // check if can over write the certificate if (readOnly) throw new CertificateParsingException("Cannot overwrite existing certificate"); readOnly = true; DerValue seq[] = new DerValue[3]; seq[0] = val.data.getDerValue(); seq[1] = val.data.getDerValue(); seq[2] = val.data.getDerValue(); if (val.data.available() != 0) { throw new CertificateParsingException("signed overrun, bytes = " + val.data.available()); } if (seq[0].tag != DerValue.tag_Sequence) { throw new CertificateParsingException("signed fields invalid"); } algId = AlgorithmId.parse(seq[1]); signature = seq[2].getBitString(); if (seq[1].data.available() != 0) { throw new CertificateParsingException("algid field overrun"); } if (seq[2].data.available() != 0) throw new CertificateParsingException("signed fields overrun"); // The CertificateInfo if (info == null) { info = new X509CertInfo(seq[0]); } } /** * Serialization write ... X.509 certificates serialize as * themselves, and they're parsed when they get read back. * (Actually they serialize as some type data from the * serialization subsystem, then the cert data.) */ private void writeObject(ObjectOutputStream stream) throws CertificateException, IOException { encode(stream); } /** * Serialization read ... X.509 certificates serialize as * themselves, and they're parsed when they get read back. */ private void readObject(ObjectInputStream stream) throws CertificateException, IOException { decode(stream); } protected static class CertificateRep1 implements java.io.Serializable { /** * */ private static final long serialVersionUID = -5207881613631592409L; private String type1; private byte[] data1; /** * Construct the alternate Certificate class with the Certificate * type and Certificate encoding bytes. * *

* * @param type the standard name of the Certificate type. *

* * @param data the Certificate data. */ protected CertificateRep1(String type, byte[] data) { this.type1 = type; this.data1 = data; } /** * Resolve the Certificate Object. * *

* * @return the resolved Certificate Object. * * @throws java.io.ObjectStreamException if the Certificate could not * be resolved. */ protected Object readResolve() throws java.io.ObjectStreamException { try { @SuppressWarnings("unused") CertificateFactory cf = CertificateFactory.getInstance(type1); // check for errors return new X509CertImpl(data1); /* return cf.generateCertificate (new java.io.ByteArrayInputStream(data1)); */ } catch (CertificateException e) { throw new java.io.NotSerializableException("java.security.cert.Certificate: " + type1 + ": " + e.getMessage()); } } } @Override protected Object writeReplace() throws java.io.ObjectStreamException { try { return new CertificateRep1("X.509", getEncoded()); } catch (CertificateException e) { throw new java.io.NotSerializableException("java.security.cert.Certificate: " + "X.509" + ": " + e.getMessage()); } } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/X509CertInfo.java000066400000000000000000001016531412550063600271340ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.Serializable; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateParsingException; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * The X509CertInfo class represents X.509 certificate information. * *

* X.509 certificates have several base data elements, including: *

    * *
  • The Subject Name, an X.500 Distinguished Name for the entity (subject) for which the certificate was * issued. * *
  • The Subject Public Key, the public key of the subject. This is one of the most important parts of the * certificate. * *
  • The Validity Period, a time period (e.g. six months) within which the certificate is valid (unless * revoked). * *
  • The Issuer Name, an X.500 Distinguished Name for the Certificate Authority (CA) which issued the * certificate. * *
  • A Serial Number assigned by the CA, for use in certificate revocation and other applications. * *
* * @author Amit Kapoor * @author Hemma Prafullchandra * @version 1.16 * @see CertAttrSet * @see Serializable * @see X509CertImpl */ public class X509CertInfo implements CertAttrSet, Serializable { /** * */ private static final long serialVersionUID = -5094073467876311577L; /** * Identifier for this attribute, to be used with the * get, set, delete methods of Certificate, x509 type. */ public static final String IDENT = "x509.info"; // Certificate attribute names public static final String NAME = "info"; public static final String VERSION = CertificateVersion.NAME; public static final String SERIAL_NUMBER = CertificateSerialNumber.NAME; public static final String ALGORITHM_ID = CertificateAlgorithmId.NAME; public static final String ISSUER = CertificateIssuerName.NAME; public static final String VALIDITY = CertificateValidity.NAME; public static final String SUBJECT = CertificateSubjectName.NAME; public static final String KEY = CertificateX509Key.NAME; public static final String ISSUER_ID = CertificateIssuerUniqueIdentity.NAME; public static final String SUBJECT_ID = CertificateSubjectUniqueIdentity.NAME; public static final String EXTENSIONS = CertificateExtensions.NAME; // X509.v1 data protected CertificateVersion version = new CertificateVersion(); protected CertificateSerialNumber serialNum = null; protected CertificateAlgorithmId algId = null; protected CertificateIssuerName issuer = null; protected CertificateValidity interval = null; protected CertificateSubjectName subject = null; protected CertificateX509Key pubKey = null; // X509.v2 & v3 extensions protected CertificateIssuerUniqueIdentity issuerUniqueId = null; protected CertificateSubjectUniqueIdentity subjectUniqueId = null; // X509.v3 extensions protected CertificateExtensions extensions = null; // Attribute numbers for internal manipulation private static final int ATTR_VERSION = 1; private static final int ATTR_SERIAL = 2; private static final int ATTR_ALGORITHM = 3; private static final int ATTR_ISSUER = 4; private static final int ATTR_VALIDITY = 5; private static final int ATTR_SUBJECT = 6; private static final int ATTR_KEY = 7; private static final int ATTR_ISSUER_ID = 8; private static final int ATTR_SUBJECT_ID = 9; private static final int ATTR_EXTENSIONS = 10; // DER encoded CertificateInfo data private byte[] rawCertInfo = null; // The certificate attribute name to integer mapping stored here private static final Hashtable map = new Hashtable(); static { map.put(VERSION, Integer.valueOf(ATTR_VERSION)); map.put(SERIAL_NUMBER, Integer.valueOf(ATTR_SERIAL)); map.put(ALGORITHM_ID, Integer.valueOf(ATTR_ALGORITHM)); map.put(ISSUER, Integer.valueOf(ATTR_ISSUER)); map.put(VALIDITY, Integer.valueOf(ATTR_VALIDITY)); map.put(SUBJECT, Integer.valueOf(ATTR_SUBJECT)); map.put(KEY, Integer.valueOf(ATTR_KEY)); map.put(ISSUER_ID, Integer.valueOf(ATTR_ISSUER_ID)); map.put(SUBJECT_ID, Integer.valueOf(ATTR_SUBJECT_ID)); map.put(EXTENSIONS, Integer.valueOf(ATTR_EXTENSIONS)); } /** * Construct an uninitialized X509CertInfo on which * decode must later be called (or which may be deserialized). */ public X509CertInfo() { } /** * Unmarshals a certificate from its encoded form, parsing the * encoded bytes. This form of constructor is used by agents which * need to examine and use certificate contents. That is, this is * one of the more commonly used constructors. Note that the buffer * must include only a certificate, and no "garbage" may be left at * the end. If you need to ignore data at the end of a certificate, * use another constructor. * * @param cert the encoded bytes, with no trailing data. * @exception CertificateParsingException on parsing errors. */ public X509CertInfo(byte[] cert) throws CertificateParsingException { try { DerValue in = new DerValue(cert); parse(in); } catch (IOException e) { throw new CertificateParsingException(e); } } /** * Unmarshal a certificate from its encoded form, parsing a DER value. * This form of constructor is used by agents which need to examine * and use certificate contents. * * @param derVal the der value containing the encoded cert. * @exception CertificateParsingException on parsing errors. */ public X509CertInfo(DerValue derVal) throws CertificateParsingException { try { parse(derVal); } catch (IOException e) { throw new CertificateParsingException(e); } } /** * Decode an X.509 certificate from an input stream. * * @param in an input stream holding at least one certificate * @exception CertificateParsingException on decoding errors. * @exception IOException on other errors. */ @Override public void decode(InputStream in) throws CertificateParsingException, IOException { DerValue val = new DerValue(in); parse(val); } /** * Appends the certificate to an output stream. * * @param out an output stream to which the certificate is appended. * @exception CertificateException on encoding errors. * @exception IOException on other errors. */ @Override public void encode(OutputStream out) throws CertificateException, IOException { encode(out, false); } /** * Appends the certificate to an output stream. * * @param out An output stream to which the certificate is appended. * @param ignoreCache Whether to ignore the internal cache when encoding. * (the cache can easily become out of date). */ public void encode(OutputStream out, boolean ignoreCache) throws IOException, CertificateException { if (ignoreCache || (rawCertInfo == null)) { DerOutputStream tmp = new DerOutputStream(); emit(tmp); rawCertInfo = tmp.toByteArray(); } out.write(rawCertInfo); } /** * Return an enumeration of names of attributes existing within this * attribute. */ @Override public Enumeration getAttributeNames() { Vector elements = new Vector(); elements.addElement(VERSION); elements.addElement(SERIAL_NUMBER); elements.addElement(ALGORITHM_ID); elements.addElement(ISSUER); elements.addElement(VALIDITY); elements.addElement(SUBJECT); elements.addElement(KEY); elements.addElement(ISSUER_ID); elements.addElement(SUBJECT_ID); elements.addElement(EXTENSIONS); return (elements.elements()); } /** * Return the name of this attribute. */ @Override public String getName() { return (NAME); } /** * Returns the encoded certificate info. * * @exception CertificateEncodingException on encoding information errors. */ public byte[] getEncodedInfo() throws CertificateEncodingException { return getEncodedInfo(false); } public byte[] getEncodedInfo(boolean ignoreCache) throws CertificateEncodingException { try { if (ignoreCache || (rawCertInfo == null)) { DerOutputStream tmp = new DerOutputStream(); emit(tmp); rawCertInfo = tmp.toByteArray(); } byte[] dup = new byte[rawCertInfo.length]; System.arraycopy(rawCertInfo, 0, dup, 0, dup.length); return dup; } catch (IOException e) { throw new CertificateEncodingException(e); } catch (CertificateException e) { throw new CertificateEncodingException(e); } } /** * Compares two X509CertInfo objects. This is false if the * certificates are not both X.509 certs, otherwise it * compares them as binary data. * * @param other the object being compared with this one * @return true iff the certificates are equivalent */ @Override public boolean equals(Object other) { if (other instanceof X509CertInfo) { return equals((X509CertInfo) other); } else { return false; } } /** * Compares two certificates, returning false if any data * differs between the two. * * @param other the object being compared with this one * @return true iff the certificates are equivalent */ public boolean equals(X509CertInfo other) { if (this == other) { return (true); } else if (rawCertInfo == null || other.rawCertInfo == null) { return (false); } else if (rawCertInfo.length != other.rawCertInfo.length) { return (false); } for (int i = 0; i < rawCertInfo.length; i++) { if (rawCertInfo[i] != other.rawCertInfo[i]) { return (false); } } return (true); } /** * Calculates a hash code value for the object. Objects * which are equal will also have the same hashcode. */ @Override public int hashCode() { int retval = 0; for (int i = 1; i < rawCertInfo.length; i++) { retval += rawCertInfo[i] * i; } return (retval); } /** * Returns a printable representation of the certificate. */ @Override public String toString() { if (subject == null || pubKey == null || interval == null || issuer == null || algId == null || serialNum == null) { throw new NullPointerException("X.509 cert is incomplete"); } StringBuffer sb = new StringBuffer("[\n" + " " + version.toString() + "\n" + " Subject: " + subject.toString() + "\n" + " Signature Algorithm: " + algId.toString() + "\n" + " Key: " + pubKey.toString() + "\n"); sb.append(" " + interval.toString() + "\n" + " Issuer: " + issuer.toString() + "\n" + " " + serialNum.toString() + "\n"); // optional v2, v3 extras if (issuerUniqueId != null) { sb.append(" Issuer Id:\n" + issuerUniqueId.toString() + "\n"); } if (subjectUniqueId != null) { sb.append(" Subject Id:\n" + subjectUniqueId.toString() + "\n"); } if (extensions != null) { org.mozilla.jss.netscape.security.util.PrettyPrintFormat pp = new org.mozilla.jss.netscape.security.util.PrettyPrintFormat(" ", 20); for (int i = 0; i < extensions.size(); i++) { sb.append(" Extension[" + i + "] = "); Extension ext = extensions.elementAt(i); DerOutputStream out = null; try { if (OIDMap.getClass(ext.getExtensionId()) == null) { sb.append(ext.toString()); byte[] extValue = ext.getExtensionValue(); if (extValue != null) { out = new DerOutputStream(); out.putOctetString(extValue); extValue = out.toByteArray(); String extValuebits = pp.toHexString(extValue); sb.append("Extension unknown: " + "DER encoded OCTET string =\n" + extValuebits); } } else sb.append(ext.toString()); //sub-class exists } catch (CertificateException e) { sb.append(", Error parsing this extension"); } catch (IOException e) { sb.append(", Error parsing this extension"); } finally { if (out != null) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } } } sb.append("\n]"); return sb.toString(); } /** * Set the certificate attribute. * * @param name the name of the Certificate attribute. * @param val the value of the Certificate attribute. * @exception CertificateException on invalid attributes. * @exception IOException on other errors. */ @Override public void set(String name, Object val) throws CertificateException, IOException { X509AttributeName attrName = new X509AttributeName(name); int attr = attributeMap(attrName.getPrefix()); if (attr == 0) { throw new CertificateException("Attribute name not recognized: " + name); } // set rawCertInfo to null, so that we are forced to re-encode rawCertInfo = null; switch (attr) { case ATTR_VERSION: if (attrName.getSuffix() == null) { setVersion(val); } else { version.set(attrName.getSuffix(), val); } break; case ATTR_SERIAL: if (attrName.getSuffix() == null) { setSerialNumber(val); } else { serialNum.set(attrName.getSuffix(), val); } break; case ATTR_ALGORITHM: if (attrName.getSuffix() == null) { setAlgorithmId(val); } else { algId.set(attrName.getSuffix(), val); } break; case ATTR_ISSUER: if (attrName.getSuffix() == null) { setIssuer(val); } else { issuer.set(attrName.getSuffix(), val); } break; case ATTR_VALIDITY: if (attrName.getSuffix() == null) { setValidity(val); } else { interval.set(attrName.getSuffix(), val); } break; case ATTR_SUBJECT: if (attrName.getSuffix() == null) { setSubject(val); } else { subject.set(attrName.getSuffix(), val); } break; case ATTR_KEY: if (attrName.getSuffix() == null) { setKey(val); } else { pubKey.set(attrName.getSuffix(), val); } break; case ATTR_ISSUER_ID: if (attrName.getSuffix() == null) { setIssuerUniqueId(val); } else { issuerUniqueId.set(attrName.getSuffix(), val); } break; case ATTR_SUBJECT_ID: if (attrName.getSuffix() == null) { setSubjectUniqueId(val); } else { subjectUniqueId.set(attrName.getSuffix(), val); } break; case ATTR_EXTENSIONS: if (attrName.getSuffix() == null) { setExtensions(val); } else { extensions.set(attrName.getSuffix(), val); } break; } } /** * Delete the certificate attribute. * * @param name the name of the Certificate attribute. * @exception CertificateException on invalid attributes. * @exception IOException on other errors. */ @Override public void delete(String name) throws CertificateException, IOException { X509AttributeName attrName = new X509AttributeName(name); int attr = attributeMap(attrName.getPrefix()); if (attr == 0) { throw new CertificateException("Attribute name not recognized: " + name); } // set rawCertInfo to null, so that we are forced to re-encode rawCertInfo = null; switch (attr) { case ATTR_VERSION: if (attrName.getSuffix() == null) { version = null; } else { version.delete(attrName.getSuffix()); } break; case (ATTR_SERIAL): if (attrName.getSuffix() == null) { serialNum = null; } else { serialNum.delete(attrName.getSuffix()); } break; case (ATTR_ALGORITHM): if (attrName.getSuffix() == null) { algId = null; } else { algId.delete(attrName.getSuffix()); } break; case (ATTR_ISSUER): if (attrName.getSuffix() == null) { issuer = null; } else { issuer.delete(attrName.getSuffix()); } break; case (ATTR_VALIDITY): if (attrName.getSuffix() == null) { interval = null; } else { interval.delete(attrName.getSuffix()); } break; case (ATTR_SUBJECT): if (attrName.getSuffix() == null) { subject = null; } else { subject.delete(attrName.getSuffix()); } break; case (ATTR_KEY): if (attrName.getSuffix() == null) { pubKey = null; } else { pubKey.delete(attrName.getSuffix()); } break; case (ATTR_ISSUER_ID): if (attrName.getSuffix() == null) { issuerUniqueId = null; } else { issuerUniqueId.delete(attrName.getSuffix()); } break; case (ATTR_SUBJECT_ID): if (attrName.getSuffix() == null) { subjectUniqueId = null; } else { subjectUniqueId.delete(attrName.getSuffix()); } break; case (ATTR_EXTENSIONS): if (attrName.getSuffix() == null) { extensions = null; } else { extensions.delete(attrName.getSuffix()); } break; } } /** * Get the certificate attribute. * * @param name the name of the Certificate attribute. * * @exception CertificateException on invalid attributes. * @exception IOException on other errors. */ @Override public Object get(String name) throws CertificateException, IOException { X509AttributeName attrName = new X509AttributeName(name); int attr = attributeMap(attrName.getPrefix()); if (attr == 0) { throw new CertificateParsingException( "Attribute name not recognized: " + name); } switch (attr) { case (ATTR_VERSION): if (attrName.getSuffix() == null) { return (version); } else { return (version.get(attrName.getSuffix())); } case (ATTR_SERIAL): if (attrName.getSuffix() == null) { return (serialNum); } else { return (serialNum.get(attrName.getSuffix())); } case (ATTR_ALGORITHM): if (attrName.getSuffix() == null) { return (algId); } else { return (algId.get(attrName.getSuffix())); } case (ATTR_ISSUER): if (attrName.getSuffix() == null) { return (issuer); } else { return (issuer.get(attrName.getSuffix())); } case (ATTR_VALIDITY): if (attrName.getSuffix() == null) { return (interval); } else { return (interval.get(attrName.getSuffix())); } case (ATTR_SUBJECT): if (attrName.getSuffix() == null) { return (subject); } else { return (subject.get(attrName.getSuffix())); } case (ATTR_KEY): if (attrName.getSuffix() == null) { return (pubKey); } else { return (pubKey.get(attrName.getSuffix())); } case (ATTR_ISSUER_ID): if (attrName.getSuffix() == null) { return (issuerUniqueId); } else { if (issuerUniqueId == null) return null; else return (issuerUniqueId.get(attrName.getSuffix())); } case (ATTR_SUBJECT_ID): if (attrName.getSuffix() == null) { return (subjectUniqueId); } else { if (subjectUniqueId == null) return null; else return (subjectUniqueId.get(attrName.getSuffix())); } case (ATTR_EXTENSIONS): if (attrName.getSuffix() == null) { return (extensions); } else { if (extensions == null) return null; else return (extensions.get(attrName.getSuffix())); } } return null; } /* * This routine unmarshals the certificate information. */ private void parse(DerValue val) throws CertificateParsingException, IOException { DerInputStream in; DerValue tmp; if (val.tag != DerValue.tag_Sequence) { throw new CertificateParsingException("signed fields invalid"); } rawCertInfo = val.toByteArray(); in = val.data; // Version tmp = in.getDerValue(); if (tmp.isContextSpecific((byte) 0)) { version = new CertificateVersion(tmp); tmp = in.getDerValue(); } // Serial number ... an integer serialNum = new CertificateSerialNumber(tmp); // Algorithm Identifier algId = new CertificateAlgorithmId(in); // Issuer name issuer = new CertificateIssuerName(in); // validity: SEQUENCE { start date, end date } interval = new CertificateValidity(in); // subject name subject = new CertificateSubjectName(in); // public key pubKey = new CertificateX509Key(in); // If more data available, make sure version is not v1. if (in.available() != 0) { if (version.compare(CertificateVersion.V1) == 0) { throw new CertificateParsingException("excess cert data"); } } else { return; } // Get the issuerUniqueId if present tmp = in.getDerValue(); if (tmp.isContextSpecific((byte) 1)) { issuerUniqueId = new CertificateIssuerUniqueIdentity(tmp); if (in.available() == 0) { return; } tmp = in.getDerValue(); } // Get the subjectUniqueId if present. if (tmp.isContextSpecific((byte) 2)) { subjectUniqueId = new CertificateSubjectUniqueIdentity(tmp); if (in.available() == 0) { return; } tmp = in.getDerValue(); } // Get the extensions. if (version.compare(CertificateVersion.V3) != 0) { throw new CertificateParsingException("excess cert data"); } if (tmp.isConstructed() && tmp.isContextSpecific((byte) 3)) { extensions = new CertificateExtensions(tmp.data); } } /* * Marshal the contents of a "raw" certificate into a DER sequence. */ private void emit(DerOutputStream out) throws CertificateException, IOException { DerOutputStream tmp = new DerOutputStream(); // version number, iff not V1 version.encode(tmp); // Encode serial number, issuer signing algorithm, issuer name // and validity serialNum.encode(tmp); algId.encode(tmp); issuer.encode(tmp); interval.encode(tmp); // Encode subject (principal) and associated key subject.encode(tmp); pubKey.encode(tmp); // Encode issuerUniqueId & subjectUniqueId. if (issuerUniqueId != null) { issuerUniqueId.encode(tmp); } if (subjectUniqueId != null) { subjectUniqueId.encode(tmp); } // Write all the extensions. if (extensions != null) { extensions.encode(tmp); } // Wrap the data; encoding of the "raw" cert is now complete. out.write(DerValue.tag_Sequence, tmp); } /** * Serialization write ... X.509 certificates serialize as * themselves, and they're parsed when they get read back. * (Actually they serialize as some type data from the * serialization subsystem, then the cert data.) */ private void writeObject(ObjectOutputStream stream) throws CertificateException, IOException { encode(stream); } /** * Serialization read ... X.509 certificates serialize as * themselves, and they're parsed when they get read back. */ private void readObject(ObjectInputStream stream) throws CertificateException, IOException { decode(stream); } /** * Returns the integer attribute number for the passed attribute name. */ private int attributeMap(String name) { Integer num = map.get(name); if (num == null) { return (0); } return (num.intValue()); } /** * Set the version number of the certificate. * * @param val the Object class value for the Extensions * @exception CertificateException on invalid data. */ private void setVersion(Object val) throws CertificateException { if (!(val instanceof CertificateVersion)) { throw new CertificateException("Version class type invalid."); } version = (CertificateVersion) val; } /** * Set the serial number of the certificate. * * @param val the Object class value for the CertificateSerialNumber * @exception CertificateException on invalid data. */ private void setSerialNumber(Object val) throws CertificateException { if (!(val instanceof CertificateSerialNumber)) { throw new CertificateException("SerialNumber class type invalid."); } serialNum = (CertificateSerialNumber) val; } /** * Set the algorithm id of the certificate. * * @param val the Object class value for the AlgorithmId * @exception CertificateException on invalid data. */ private void setAlgorithmId(Object val) throws CertificateException { if (!(val instanceof CertificateAlgorithmId)) { throw new CertificateException( "AlgorithmId class type invalid."); } algId = (CertificateAlgorithmId) val; } /** * Set the issuer name of the certificate. * * @param val the Object class value for the issuer * @exception CertificateException on invalid data. */ private void setIssuer(Object val) throws CertificateException { if (!(val instanceof CertificateIssuerName)) { throw new CertificateException( "Issuer class type invalid."); } issuer = (CertificateIssuerName) val; } public CertificateIssuerName getIssuerObj() { return issuer; } /** * Set the validity interval of the certificate. * * @param val the Object class value for the CertificateValidity * @exception CertificateException on invalid data. */ private void setValidity(Object val) throws CertificateException { if (!(val instanceof CertificateValidity)) { throw new CertificateException( "CertificateValidity class type invalid."); } interval = (CertificateValidity) val; } /** * Set the subject name of the certificate. * * @param val the Object class value for the Subject * @exception CertificateException on invalid data. */ private void setSubject(Object val) throws CertificateException { if (!(val instanceof CertificateSubjectName)) { throw new CertificateException( "Subject class type invalid."); } subject = (CertificateSubjectName) val; } public CertificateSubjectName getSubjectObj() { return subject; } /** * Set the public key in the certificate. * * @param val the Object class value for the PublicKey * @exception CertificateException on invalid data. */ private void setKey(Object val) throws CertificateException { if (!(val instanceof CertificateX509Key)) { throw new CertificateException( "Key class type invalid."); } pubKey = (CertificateX509Key) val; } /** * Set the Issuer Unique Identity in the certificate. * * @param val the Object class value for the IssuerUniqueId * @exception CertificateException */ private void setIssuerUniqueId(Object val) throws CertificateException { if (version.compare(CertificateVersion.V2) < 0) { throw new CertificateException("Invalid version"); } if (!(val instanceof CertificateIssuerUniqueIdentity)) { throw new CertificateException( "IssuerUniqueId class type invalid."); } issuerUniqueId = (CertificateIssuerUniqueIdentity) val; } /** * Set the Subject Unique Identity in the certificate. * * @param val the Object class value for the SubjectUniqueId * @exception CertificateException */ private void setSubjectUniqueId(Object val) throws CertificateException { if (version.compare(CertificateVersion.V2) < 0) { throw new CertificateException("Invalid version"); } if (!(val instanceof CertificateSubjectUniqueIdentity)) { throw new CertificateException( "SubjectUniqueId class type invalid."); } subjectUniqueId = (CertificateSubjectUniqueIdentity) val; } /** * Set the extensions in the certificate. * * @param val the Object class value for the Extensions * @exception CertificateException */ private void setExtensions(Object val) throws CertificateException { if (version.compare(CertificateVersion.V3) < 0) { throw new CertificateException("Invalid version"); } if (!(val instanceof CertificateExtensions)) { throw new CertificateException( "Extensions class type invalid."); } extensions = (CertificateExtensions) val; } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/X509ExtensionException.java000066400000000000000000000043611412550063600312540ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.security.GeneralSecurityException; /** * X.509 Extension Exception. * * @author Hemma Prafullchandra * 1.2 */ public class X509ExtensionException extends GeneralSecurityException { /** * */ private static final long serialVersionUID = 8152491877676477910L; /** * Constructs an X509ExtensionException with no detail message. A * detail message is a String that describes this particular * exception. */ public X509ExtensionException() { super(); } /** * Constructs the exception with the specified detail * message. A detail message is a String that describes this * particular exception. * * @param mesg the detail message. */ public X509ExtensionException(String mesg) { super(mesg); } /** * Constructs the exception with the specified detail * message and cause of this exception. A detail message is a * String that describes this particular exception. * * @param mesg the detail message. * @param cause the cause of this exception. */ public X509ExtensionException(String mesg, Throwable cause) { super(mesg, cause); } /** * Constructs the exception with the specified cause of * this exception. * * @param cause the cause of this exception. */ public X509ExtensionException(Throwable cause) { super(cause); } } jss-5.0.0/src/main/java/org/mozilla/jss/netscape/security/x509/X509Key.java000066400000000000000000000422641412550063600261550ustar00rootroot00000000000000// --- BEGIN COPYRIGHT BLOCK --- // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; version 2 of the License. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License along // with this program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // // (C) 2007 Red Hat, Inc. // All rights reserved. // --- END COPYRIGHT BLOCK --- package org.mozilla.jss.netscape.security.x509; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.lang.reflect.InvocationTargetException; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.Provider; import java.security.PublicKey; import java.security.Security; import java.security.spec.InvalidKeySpecException; import java.security.spec.X509EncodedKeySpec; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; /** * Holds an X.509 key, for example a public key found in an X.509 * certificate. Includes a description of the algorithm to be used * with the key; these keys normally are used as * "SubjectPublicKeyInfo". * *

* While this class can represent any kind of X.509 key, it may be desirable to provide subclasses which understand how * to parse keying data. For example, RSA public keys have two members, one for the public modulus and one for the prime * exponent. If such a class is provided, it is used when parsing X.509 keys. If one is not provided, the key still * parses correctly. * * @version 1.74, 97/12/10 * @author David Brownell */ public class X509Key implements PublicKey { /** use serialVersionUID from JDK 1.1. for interoperability */ private static final long serialVersionUID = -5359250853002055002L; /* The algorithm information (name, parameters, etc). */ protected AlgorithmId algid; /* The key bytes, without the algorithm information */ protected byte[] key; /* The encoding for the key. */ protected byte[] encodedKey; /** * Default constructor. The key constructed must have its key * and algorithm initialized before it may be used, for example * by using decode. */ public X509Key() { } /* * Build and initialize as a "default" key. All X.509 key * data is stored and transmitted losslessly, but no knowledge * about this particular algorithm is available. */ public X509Key(AlgorithmId algid, byte[] key) throws InvalidKeyException { this.algid = algid; this.key = key; encode(); } /** * Construct X.509 subject public key from a DER value. If * the runtime environment is configured with a specific class for * this kind of key, a subclass is returned. Otherwise, a generic * X509Key object is returned. * *

* This mechanism gurantees that keys (and algorithms) may be freely manipulated and transferred, without risk of * losing information. Also, when a key (or algorithm) needs some special handling, that specific need can be * accomodated. * * @param in the DER-encoded SubjectPublicKeyInfo value * @exception IOException on data format errors */ public static X509Key parse(DerValue in) throws IOException { AlgorithmId algorithm; X509Key subjectKey; if (in.tag != DerValue.tag_Sequence) throw new IOException("corrupt subject key"); algorithm = AlgorithmId.parse(in.data.getDerValue()); try { subjectKey = buildX509Key(algorithm, in.data.getBitString()); } catch (InvalidKeyException e) { throw new IOException("subject key, " + e.getMessage()); } if (in.data.available() != 0) throw new IOException("excess subject key"); return subjectKey; } /** * Parse the key bits. This may be redefined by subclasses to take * advantage of structure within the key. For example, RSA public * keys encapsulate two unsigned integers (modulus and exponent) as * DER values within the key bits; Diffie-Hellman and * DSS/DSA keys encapsulate a single unsigned integer. * *

* This function is called when creating X.509 SubjectPublicKeyInfo values using the X509Key member functions, such * as parse and decode. * * @exception IOException on parsing errors. * @exception InvalidKeyException on invalid key encodings. */ protected void parseKeyBits() throws IOException, InvalidKeyException { encode(); } /* * Factory interface, building the kind of key associated with this * specific algorithm ID or else returning this generic base class. * See the description above. */ static X509Key buildX509Key(AlgorithmId algid, byte[] key) throws IOException, InvalidKeyException { /* * Use the algid and key parameters to produce the ASN.1 encoding * of the key, which will then be used as the input to the * key factory. */ DerOutputStream x509EncodedKeyStream = new DerOutputStream(); encode(x509EncodedKeyStream, algid, key); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(x509EncodedKeyStream.toByteArray()); try { // Instantiate the key factory of the appropriate algorithm KeyFactory keyFac = null; if (Security.getProvider("Mozilla-JSS") == null) { keyFac = KeyFactory.getInstance(algid.getName()); } else { keyFac = KeyFactory.getInstance(algid.getName(), "Mozilla-JSS"); } // Generate the public key PublicKey pubKey = keyFac.generatePublic(x509KeySpec); if (pubKey instanceof X509Key) { /* * Return specialized X509Key, where the structure within the * key has been parsed */ return (X509Key) pubKey; } } catch (NoSuchAlgorithmException e) { // Return generic X509Key with opaque key data (see below) } catch (InvalidKeySpecException e) { throw new InvalidKeyException(e.toString()); } catch (Exception e) { throw new InvalidKeyException(e.toString()); } /* * Try again using JDK1.1-style for backwards compatibility. */ String classname = ""; try { Provider sunProvider; sunProvider = Security.getProvider("SUN"); if (sunProvider == null) throw new InstantiationException(); classname = sunProvider.getProperty("PublicKey.X.509." + algid.getName()); if (classname == null) { throw new InstantiationException(); } Class keyClass = Class.forName(classname); Object inst; X509Key result; inst = keyClass.getConstructor().newInstance( sunProvider.getProperty("PublicKey.X.509." + algid.getName())); if (inst instanceof X509Key) { result = (X509Key) inst; result.algid = algid; result.key = key; result.parseKeyBits(); return result; } } catch (ClassNotFoundException e) { } catch (InstantiationException e) { } catch (IllegalAccessException e) { throw new IOException("IllegalAccessException : " + e.getMessage(), e); } catch (NoSuchMethodException e) { } catch (InvocationTargetException e) { throw new IOException("InvocationTargetException : " + e.getMessage(), e); } X509Key result = new X509Key(); result.algid = algid; result.key = key; return result; } /** * Returns the algorithm to be used with this key. */ @Override public String getAlgorithm() { return algid.getName(); } /** * Returns the algorithm ID to be used with this key. */ public AlgorithmId getAlgorithmId() { return algid; } /** * Encode SubjectPublicKeyInfo sequence on the DER output stream. * * @exception IOException on encoding errors. */ public final void encode(DerOutputStream out) throws IOException { encode(out, this.algid, this.key); } /** * Returns the DER-encoded form of the key as a byte array. */ @Override public synchronized byte[] getEncoded() { byte[] result = null; try { result = encode(); } catch (InvalidKeyException e) { } return result; } /** * Returns the format for this key: "X.509" */ @Override public String getFormat() { return "X.509"; } /** * Returns the raw key as a byte array */ public byte[] getKey() { return key; } /** * Returns the DER-encoded form of the key as a byte array. * * @exception InvalidKeyException on encoding errors. */ public byte[] encode() throws InvalidKeyException { if (encodedKey == null) { try { DerOutputStream out; out = new DerOutputStream(); encode(out); encodedKey = out.toByteArray(); } catch (IOException e) { throw new InvalidKeyException("IOException : " + e.getMessage()); } } return copyEncodedKey(encodedKey); } /* * Returns a printable representation of the key */ @Override public String toString() { org.mozilla.jss.netscape.security.util.PrettyPrintFormat pp = new org.mozilla.jss.netscape.security.util.PrettyPrintFormat(" ", 20); String keybits = pp.toHexString(key); return "algorithm = " + algid.toString() + ", unparsed keybits = \n" + keybits; } /** * Initialize an X509Key object from an input stream. The data on that * input stream must be encoded using DER, obeying the X.509 SubjectPublicKeyInfo format. That is, the * data is a * sequence consisting of an algorithm ID and a bit string which holds * the key. (That bit string is often used to encapsulate another DER * encoded sequence.) * *

* Subclasses should not normally redefine this method; they should instead provide a parseKeyBits * method to parse any fields inside the key member. * *

* The exception to this rule is that since private keys need not be encoded using the X.509 * SubjectPublicKeyInfo format, private keys may override this method, encode, and of * course getFormat. * * @param in an input stream with a DER-encoded X.509 * SubjectPublicKeyInfo value * @exception InvalidKeyException on parsing errors. */ public void decode(InputStream in) throws InvalidKeyException { DerValue val; try { val = new DerValue(in); if (val.tag != DerValue.tag_Sequence) throw new InvalidKeyException("invalid key format"); algid = AlgorithmId.parse(val.data.getDerValue()); key = val.data.getBitString(); parseKeyBits(); if (val.data.available() != 0) throw new InvalidKeyException("excess key data"); } catch (IOException e) { // e.printStackTrace (); throw new InvalidKeyException("IOException : " + e.getMessage()); } } public void decode(byte[] encodedKey) throws InvalidKeyException { decode(new ByteArrayInputStream(encodedKey)); } /** * Serialization write ... X.509 keys serialize as * themselves, and they're parsed when they get read back. */ private void writeObject(java.io.ObjectOutputStream stream) throws IOException { stream.write(getEncoded()); } /** * Serialization read ... X.509 keys serialize as * themselves, and they're parsed when they get read back. */ private void readObject(ObjectInputStream stream) throws IOException { try { decode(stream); } catch (InvalidKeyException e) { e.printStackTrace(); throw new IOException("deserialized key is invalid: " + e.getMessage()); } } @Override public boolean equals(Object object) { if (this == object) { return true; } if (object instanceof Key) { Key key = (Key) object; byte[] b1; if (encodedKey != null) { b1 = encodedKey; } else { b1 = getEncoded(); } byte[] b2 = key.getEncoded(); return java.security.MessageDigest.isEqual(b1, b2); } return false; } /** * Calculates a hash code value for the object. Objects * which are equal will also have the same hashcode. */ @Override public int hashCode() { int retval = 0; byte[] b1 = getEncoded(); for (int i = 1; i < b1.length; i++) { retval += b1[i] * i; } return (retval); } /* * Make a copy of the encoded key. */ private byte[] copyEncodedKey(byte[] encodedKey) { int len = encodedKey.length; byte[] copy = new byte[len]; System.arraycopy(encodedKey, 0, copy, 0, len); return copy; } /* * Produce SubjectPublicKey encoding from algorithm id and key material. */ static void encode(DerOutputStream out, AlgorithmId algid, byte[] key) throws IOException { DerOutputStream tmp = new DerOutputStream(); algid.encode(tmp); tmp.putBitString(key); out.write(DerValue.tag_Sequence, tmp); } /* * parsePublicKey returns a PublicKey for use with package JSS from within netscape.security.*. * This function provide an interim solution for migrating from using the netscape.security.* package * to using the JSS package. */ public static PublicKey parsePublicKey(DerValue in) throws IOException { AlgorithmId algorithm; PublicKey subjectKey; if (in.tag != DerValue.tag_Sequence) throw new IOException("corrupt subject key"); algorithm = AlgorithmId.parse(in.data.getDerValue()); try { subjectKey = buildPublicKey(algorithm, in.data.getBitString()); } catch (InvalidKeyException e) { throw new IOException("subject key, " + e.getMessage()); } if (in.data.available() != 0) throw new IOException("excess subject key"); return subjectKey; } /* buildPublicKey returns a PublicKey for use with the JSS package from within netscape.security.*. * This function provide an interim solution for migrating from using the netscape.security.* package * to using the JSS package. */ static PublicKey buildPublicKey(AlgorithmId algid, byte[] key) throws IOException, InvalidKeyException { /* * Use the algid and key parameters to produce the ASN.1 encoding * of the key, which will then be used as the input to the * key factory. */ DerOutputStream x509EncodedKeyStream = new DerOutputStream(); encode(x509EncodedKeyStream, algid, key); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(x509EncodedKeyStream.toByteArray()); try { // Instantiate the key factory of the appropriate algorithm KeyFactory keyFac = null; if (Security.getProvider("Mozilla-JSS") == null) { keyFac = KeyFactory.getInstance(algid.getName()); } else { keyFac = KeyFactory.getInstance(algid.getName(), "Mozilla-JSS"); } // Generate the public key PublicKey pubKey = keyFac.generatePublic(x509KeySpec); /* * Return specialized X509Key, where the structure within the * key has been parsed */ return pubKey; } catch (NoSuchAlgorithmException e) { // Return generic X509Key with opaque key data (see below) throw new InvalidKeyException(e.toString()); } catch (InvalidKeySpecException e) { throw new InvalidKeyException(e.toString()); } catch (Exception e) { throw new InvalidKeyException(e.toString()); } } } jss-5.0.0/src/main/java/org/mozilla/jss/nss/000077500000000000000000000000001412550063600206115ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/nss/BadCertHandler.java000066400000000000000000000037401412550063600242620ustar00rootroot00000000000000package org.mozilla.jss.nss; /** * BadAuthHandler interface enables arbitrary certificate authentication * from a NSS cert auth hook. * * Notably, the return code from check should be a PRErrorCode, else 0. * This will be used by NSS to determine the alert to send when closing * the connection (in the event of an error). * * The concern here is that, when this is invoked synchronously, we're * called from NSS as called by Java. Certain operations may or may not * succeed or work as expected (such as raising an exception, acquiring * locks already held, etc.). */ public abstract class BadCertHandler implements Runnable { /** * When invoked via run(), the error code to pass to the * check operation. */ public int error; /** * When invoked via run(), the result of the check * operation. */ public int result; /** * Whether or not the check operation has been executed * yet, when invoked via run(). */ public boolean finished; /** * SSLFDProxy instance. */ private SSLFDProxy ssl_fd; /** * Constructor to store SSLFDProxy, error information. * * This is useful for implementations which expect to be used * via the Runnable interface, instead of called via the * synchronous certificate authentication hook in NSS. */ public BadCertHandler(SSLFDProxy fd, int error) { ssl_fd = fd; this.error = error; } /** * Returns the PRErrorCode the error validating certificate * auth, else 0. * * Note that it is up to the implementer to fetch the certificates * (via SSL.PeerCertificateChain(ssl_fd)) and validate them * properly. * * Note that returning 0 here means SECis returned */ public abstract int check(SSLFDProxy fd, int error); @Override public void run() { try { result = check(ssl_fd, error); } finally { finished = true; } } } jss-5.0.0/src/main/java/org/mozilla/jss/nss/Buffer.c000066400000000000000000000102551412550063600221710ustar00rootroot00000000000000#include #include #include #include #include "jssutil.h" #include "BufferProxy.h" #include "j_buffer.h" #include "_jni/org_mozilla_jss_nss_Buffer.h" JNIEXPORT jobject JNICALL Java_org_mozilla_jss_nss_Buffer_Create(JNIEnv *env, jclass clazz, jlong length) { j_buffer *buf = NULL; PR_ASSERT(env != NULL && length > 0); buf = jb_alloc((size_t) length); PR_ASSERT(buf != NULL); return JSS_PR_wrapJBuffer(env, &buf); } JNIEXPORT jlong JNICALL Java_org_mozilla_jss_nss_Buffer_Capacity(JNIEnv *env, jclass clazz, jobject buf) { j_buffer *real_buf = NULL; PR_ASSERT(env != NULL && buf != NULL); if (JSS_PR_unwrapJBuffer(env, buf, &real_buf) != PR_SUCCESS) { return 0; } return jb_capacity(real_buf); } JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_nss_Buffer_CanRead(JNIEnv *env, jclass clazz, jobject buf) { j_buffer *real_buf = NULL; PR_ASSERT(env != NULL && buf != NULL); if (JSS_PR_unwrapJBuffer(env, buf, &real_buf) != PR_SUCCESS) { return false; } return jb_can_read(real_buf); } JNIEXPORT jlong JNICALL Java_org_mozilla_jss_nss_Buffer_ReadCapacity(JNIEnv *env, jclass clazz, jobject buf) { j_buffer *real_buf = NULL; PR_ASSERT(env != NULL && buf != NULL); if (JSS_PR_unwrapJBuffer(env, buf, &real_buf) != PR_SUCCESS) { return 0; } return jb_read_capacity(real_buf); } JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_nss_Buffer_CanWrite(JNIEnv *env, jclass clazz, jobject buf) { j_buffer *real_buf = NULL; PR_ASSERT(env != NULL && buf != NULL); if (JSS_PR_unwrapJBuffer(env, buf, &real_buf) != PR_SUCCESS) { return false; } return jb_can_write(real_buf); } JNIEXPORT jlong JNICALL Java_org_mozilla_jss_nss_Buffer_WriteCapacity(JNIEnv *env, jclass clazz, jobject buf) { j_buffer *real_buf = NULL; PR_ASSERT(env != NULL && buf != NULL); if (JSS_PR_unwrapJBuffer(env, buf, &real_buf) != PR_SUCCESS) { return 0; } return jb_write_capacity(real_buf); } JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_nss_Buffer_Read(JNIEnv *env, jclass clazz, jobject buf, jlong length) { j_buffer *real_buf = NULL; size_t read_amount = 0; uint8_t *tmp = NULL; jbyteArray result = NULL; PR_ASSERT(env != NULL && buf != NULL && length > 0); if (JSS_PR_unwrapJBuffer(env, buf, &real_buf) != PR_SUCCESS) { return NULL; } tmp = calloc(length, sizeof(uint8_t)); read_amount = jb_read(real_buf, tmp, (size_t) length); result = JSS_ToByteArray(env, tmp, read_amount); free(tmp); return result; } JNIEXPORT jlong JNICALL Java_org_mozilla_jss_nss_Buffer_Write(JNIEnv *env, jclass clazz, jobject buf, jbyteArray input) { j_buffer *real_buf = NULL; size_t input_length = 0; uint8_t *real_input = NULL; long write_amount = -1; PR_ASSERT(env != NULL && buf != NULL); if (JSS_PR_unwrapJBuffer(env, buf, &real_buf) != PR_SUCCESS) { return write_amount; } if (!JSS_FromByteArray(env, input, &real_input, &input_length)) { return write_amount; } write_amount = jb_write(real_buf, real_input, input_length); free(real_input); return write_amount; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_Buffer_Get(JNIEnv *env, jclass clazz, jobject buf) { j_buffer *real_buf = NULL; PR_ASSERT(env != NULL && buf != NULL); if (JSS_PR_unwrapJBuffer(env, buf, &real_buf) != PR_SUCCESS) { return -1; } return jb_get(real_buf); } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_Buffer_Put(JNIEnv *env, jclass clazz, jobject buf, jbyte input) { j_buffer *real_buf = NULL; PR_ASSERT(env != NULL && buf != NULL); if (JSS_PR_unwrapJBuffer(env, buf, &real_buf) != PR_SUCCESS) { return -1; } return jb_put(real_buf, (uint8_t) input); } JNIEXPORT void JNICALL Java_org_mozilla_jss_nss_Buffer_Free(JNIEnv *env, jclass clazz, jobject buf) { j_buffer *real_buf = NULL; PR_ASSERT(env != NULL && buf != NULL); if (JSS_PR_unwrapJBuffer(env, buf, &real_buf) != PR_SUCCESS || real_buf == NULL) { return; } jb_free(real_buf); JSS_clearPtrFromProxy(env, buf); } jss-5.0.0/src/main/java/org/mozilla/jss/nss/Buffer.java000066400000000000000000000045751412550063600227000ustar00rootroot00000000000000package org.mozilla.jss.nss; public class Buffer { /** * Create a new j_buffer object with the specified number of bytes. * * See also: jb_alloc in org/mozilla/jss/ssl/javax/j_buffer.h */ public static native BufferProxy Create(long length); /** * Check the total capacity of a buffer object. * * See also: jb_capacity in org/mozilla/jss/ssl/javax/j_buffer.h */ public static native long Capacity(BufferProxy buf); /** * Check whether or not the buffer can be read from (i.e., is non-empty). * * See also: jb_can_read in org/mozilla/jss/ssl/javax/j_buffer.h */ public static native boolean CanRead(BufferProxy buf); /** * Check the remaining number of bytes that can be read from the * buffer. * * See also: jb_read_capacity in org/mozilla/jss/ssl/javax/j_buffer.h */ public static native long ReadCapacity(BufferProxy buf); /** * Check whether or not the buffer can be written to (i.e., is not full). * * See also: jb_can_write in org/mozilla/jss/ssl/javax/j_buffer.h */ public static native boolean CanWrite(BufferProxy buf); /** * Check the remaining number of bytes that can be written to the * buffer. * * See also: jb_write_capacity in org/mozilla/jss/ssl/javax/j_buffer.h */ public static native long WriteCapacity(BufferProxy buf); /** * Read the specified number of bytes from the buffer. * * See also: jb_read in org/mozilla/jss/ssl/javax/j_buffer.h */ public static native byte[] Read(BufferProxy buf, long length); /** * Write the specified bytes to the buffer. * * See also: jb_write in org/mozilla/jss/ssl/javax/j_buffer.h */ public static native long Write(BufferProxy buf, byte[] input); /** * Get a single character from the buffer. * * See also: jb_get in org/mozilla/jss/ssl/javax/j_buffer.h */ public static native int Get(BufferProxy buf); /** * Put a single character into the buffer. * * See also: jb_put in org/mozilla/jss/ssl/javax/j_buffer.h */ public static native int Put(BufferProxy buf, byte input); /** * Destroy a buffer object, freeing its resources. * * See also: jb_free in org/mozilla/jss/ssl/javax/j_buffer.h */ public static native void Free(BufferProxy buf); } jss-5.0.0/src/main/java/org/mozilla/jss/nss/BufferProxy.c000066400000000000000000000023601412550063600232310ustar00rootroot00000000000000#include #include #include "java_ids.h" #include "jssutil.h" #include "BufferProxy.h" jobject JSS_PR_wrapJBuffer(JNIEnv *env, j_buffer **buffer) { jbyteArray pointer = NULL; jclass proxyClass; jmethodID constructor; jobject bufferObj = NULL; PR_ASSERT(env != NULL && buffer != NULL && *buffer != NULL); /* convert pointer to byte array */ pointer = JSS_ptrToByteArray(env, *buffer); /* * Lookup the class and constructor */ proxyClass = (*env)->FindClass(env, BUFFER_PROXY_CLASS_NAME); if(proxyClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } constructor = (*env)->GetMethodID(env, proxyClass, PLAIN_CONSTRUCTOR, BUFFER_PROXY_CONSTRUCTOR_SIG); if(constructor == NULL) { ASSERT_OUTOFMEM(env); goto finish; } /* call the constructor */ bufferObj = (*env)->NewObject(env, proxyClass, constructor, pointer); finish: *buffer = NULL; PR_ASSERT(bufferObj || (*env)->ExceptionOccurred(env)); return bufferObj; } PRStatus JSS_PR_unwrapJBuffer(JNIEnv *env, jobject buffer_proxy, j_buffer **buffer) { return JSS_getPtrFromProxy(env, buffer_proxy, (void**)buffer); } jss-5.0.0/src/main/java/org/mozilla/jss/nss/BufferProxy.h000066400000000000000000000005321412550063600232350ustar00rootroot00000000000000#include #include "j_buffer.h" #pragma once /* Wrap a j_buffer object into a BufferProxy, freeing the buffer on error. */ jobject JSS_PR_wrapJBuffer(JNIEnv *env, j_buffer **buffer); /* Extract a j_buffer pointer from an instance of a BufferProxy. */ PRStatus JSS_PR_unwrapJBuffer(JNIEnv *env, jobject buffer_proxy, j_buffer **buffer); jss-5.0.0/src/main/java/org/mozilla/jss/nss/BufferProxy.java000066400000000000000000000007721412550063600237350ustar00rootroot00000000000000package org.mozilla.jss.nss; public class BufferProxy extends org.mozilla.jss.util.NativeProxy { public BufferProxy(byte[] pointer) { super(pointer); } /** * It is usually better to call org.mozilla.jss.nss.Buffer.Free(...) * instead. * * But this does it for you. */ @Override protected void releaseNativeResources() { Buffer.Free(this); } @Override protected void finalize() throws Throwable { super.finalize(); } } jss-5.0.0/src/main/java/org/mozilla/jss/nss/Cert.java000066400000000000000000000035501412550063600223540ustar00rootroot00000000000000package org.mozilla.jss.nss; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateNotYetValidException; import java.security.cert.CertificateParsingException; import java.security.cert.CertificateRevokedException; public class Cert { public static int MatchExceptionToNSSError(Exception excpt) { if (excpt == null) { return 0; } // Lower case, no spaces. Easier to find matches in // messy messages. String message = excpt.getMessage().toLowerCase().replaceAll("\\s+",""); if (excpt instanceof CertificateEncodingException || message.contains("encoding") || excpt instanceof CertificateParsingException || message.contains("parsing")) { return SECErrors.BAD_DER; } if (excpt instanceof CertificateExpiredException || message.contains("expired")) { return SECErrors.EXPIRED_CERTIFICATE; } if (excpt instanceof CertificateNotYetValidException || message.contains("notyetvalid") || message.contains("notvalid")) { return SECErrors.CERT_NOT_VALID; } // Check for OCSP errors prior to using a generic revoked // reason. if (message.contains("ocsp")) { return SECErrors.REVOKED_CERTIFICATE_OCSP; } if (excpt instanceof CertificateRevokedException || message.contains("revoked")) { return SECErrors.REVOKED_CERTIFICATE; } // The remaining messages don't have corresponding // exception classes. if (message.contains("issuer")) { return SECErrors.UNTRUSTED_ISSUER; } // Otherwise, use a generic error. return SECErrors.UNTRUSTED_CERT; } } jss-5.0.0/src/main/java/org/mozilla/jss/nss/CertAuthHandler.java000066400000000000000000000033511412550063600244730ustar00rootroot00000000000000package org.mozilla.jss.nss; /** * CertAuthHandler interface enables arbitrary certificate authentication * from a NSS cert auth hook. * * Notably, the return code from check should be a PRErrorCode, else 0. * This will be used by NSS to determine the alert to send when closing * the connection (in the event of an error). * * The concern here is that, when this is invoked synchronously, we're * called from NSS as called by Java. Certain operations may or may not * succeed or work as expected (such as raising an exception, acquiring * locks already held, etc.). */ public abstract class CertAuthHandler implements Runnable { /** * When invoked via run(), the result of the check * operation. */ public int result; /** * Whether or not the check operation has been executed * yet, when invoked via run(). */ public boolean finished; /** * SSLFDProxy instance. */ private SSLFDProxy ssl_fd; /** * Constructor to store SSLFDProxy information. * * This is useful for implementations which expect to be used * via the Runnable interface, instead of called via the * synchronous certificate authentication hook in NSS. */ public CertAuthHandler(SSLFDProxy fd) { ssl_fd = fd; } /** * Returns the PRErrorCode the error validating certificate * auth, else 0. * * Note that it is up to the implementer to fetch the certificates * (via SSL.PeerCertificateChain(ssl_fd)) and validate them * properly. */ public abstract int check(SSLFDProxy fd); @Override public void run() { try { result = check(ssl_fd); } finally { finished = true; } } } jss-5.0.0/src/main/java/org/mozilla/jss/nss/PR.c000066400000000000000000000232741412550063600213060ustar00rootroot00000000000000#include #include #include #include #include "jssutil.h" #include "jss_exceptions.h" #include "PRFDProxy.h" #include "BufferProxy.h" #include "BufferPRFD.h" #include "_jni/org_mozilla_jss_nss_PR.h" JNIEXPORT jobject JNICALL Java_org_mozilla_jss_nss_PR_Open(JNIEnv *env, jclass clazz, jstring name, jint flags, jint mode) { PRFileDesc *fd; const char *path; PR_ASSERT(env != NULL); PR_SetError(0, 0); path = JSS_RefJString(env, name); if (path == NULL) { return NULL; } fd = PR_Open(path, flags, mode); if (fd == NULL) { JSS_DerefJString(env, name, path); return NULL; } JSS_DerefJString(env, name, path); return JSS_PR_wrapPRFDProxy(env, &fd); } JNIEXPORT jobject JNICALL Java_org_mozilla_jss_nss_PR_NewTCPSocket(JNIEnv *env, jclass clazz) { PRFileDesc *fd; PR_ASSERT(env != NULL); PR_SetError(0, 0); fd = PR_NewTCPSocket(); if (fd == NULL) { return NULL; } return JSS_PR_wrapPRFDProxy(env, &fd); } JNIEXPORT jobject JNICALL Java_org_mozilla_jss_nss_PR_NewBufferPRFD(JNIEnv *env, jclass clazz, jobject read_buf, jobject write_buf, jbyteArray peer_info) { j_buffer *real_read_buf = NULL; j_buffer *real_write_buf = NULL; uint8_t *real_peer_info = NULL; size_t peer_info_len = 0; PRFileDesc *buf_prfd; jobject result = NULL; PR_ASSERT(env != NULL && read_buf != NULL && write_buf != NULL); PR_SetError(0, 0); if (JSS_PR_unwrapJBuffer(env, read_buf, &real_read_buf) != PR_SUCCESS) { return result; } if (JSS_PR_unwrapJBuffer(env, write_buf, &real_write_buf) != PR_SUCCESS) { return result; } if (peer_info != NULL && !JSS_FromByteArray(env, peer_info, &real_peer_info, &peer_info_len)) { return result; } buf_prfd = newBufferPRFileDesc(real_read_buf, real_write_buf, real_peer_info, peer_info_len); if (buf_prfd == NULL) { return result; } result = JSS_PR_wrapPRFDProxy(env, &buf_prfd); free(real_peer_info); return result; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_PR_Close(JNIEnv *env, jclass clazz, jobject fd, jboolean clear) { PRFileDesc *real_fd = NULL; PR_ASSERT(env != NULL); PR_SetError(0, 0); if (fd == NULL) { return PR_SUCCESS; } if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return PR_FAILURE; } PRStatus ret = PR_Close(real_fd); if (ret == PR_SUCCESS && clear == JNI_TRUE) { JSS_clearPtrFromProxy(env, fd); } return ret; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_PR_Shutdown(JNIEnv *env, jclass clazz, jobject fd, jint how) { PRFileDesc *real_fd = NULL; PR_ASSERT(env != NULL); PR_SetError(0, 0); if (fd == NULL) { return PR_SUCCESS; } if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return PR_FAILURE; } return PR_Shutdown(real_fd, how); } JNIEXPORT jobject JNICALL Java_org_mozilla_jss_nss_PR_Read(JNIEnv *env, jclass clazz, jobject fd, jint amount) { PRFileDesc *real_fd = NULL; jobject result = NULL; int read_amount = 0; int this_read = 0; uint8_t *buffer = NULL; PRSocketOptionData opt = { 0 }; PRDescType fd_type; PR_ASSERT(env != NULL && fd != NULL && amount >= 0); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return NULL; } fd_type = PR_GetDescType(real_fd); opt.value.non_blocking = PR_FALSE; if (fd_type == PR_DESC_SOCKET_TCP || fd_type == PR_DESC_SOCKET_UDP || fd_type == PR_DESC_LAYERED) { opt.option = PR_SockOpt_Nonblocking; if (PR_GetSocketOption(real_fd, &opt) != PR_SUCCESS) { /* Unable to get the value of non_blocking status; so error on * the side of caution. */ opt.value.non_blocking = PR_FALSE; } } PR_ASSERT(real_fd != NULL); buffer = calloc(amount, sizeof(uint8_t)); /* Work around a bug in NSS/NSPR: sometimes PR_Read returns a much smaller * read than expected, when it could read much more. */ while (read_amount < amount) { this_read = PR_Read(real_fd, buffer + read_amount, amount - read_amount); if (this_read <= 0) { if (PR_GetError() == 0) { /* End of data */ break; } if (PR_GetError() == PR_WOULD_BLOCK_ERROR && read_amount > 0) { /* If we've previously gotten data and we would block this * time, then we're at the end of our data. Reset the error * status and break, rather than exiting with an error. */ PR_SetError(0, 0); break; } goto done; } else { read_amount += this_read; if (opt.value.non_blocking != PR_TRUE) { /* When we're not non-blocking, it isn't necessarily safe to * call PR_Read again -- a call that would've not blocked will * now block. */ break; } } } result = JSS_ToByteArray(env, buffer, read_amount); done: free(buffer); return result; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_PR_Write(JNIEnv *env, jclass clazz, jobject fd, jbyteArray buf) { PRFileDesc *real_fd = NULL; int max_length = 0; uint8_t dummy_buffer = 0; uint8_t *buffer = NULL; int result = 0; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return 0; } PR_ASSERT(real_fd != NULL); if (buf != NULL) { max_length = (*env)->GetArrayLength(env, buf); buffer = (uint8_t*)((*env)->GetByteArrayElements(env, buf, NULL)); if (buffer == NULL) { ASSERT_OUTOFMEM(env); return 0; } } else { buffer = &dummy_buffer; max_length = 0; } result = PR_Write(real_fd, buffer, max_length); if (buf != NULL && buffer != &dummy_buffer) { (*env)->ReleaseByteArrayElements(env, buf, (jbyte *)buffer, JNI_ABORT); } return result; } JNIEXPORT jobject JNICALL Java_org_mozilla_jss_nss_PR_Recv(JNIEnv *env, jclass clazz, jobject fd, jint amount, jint flags, jlong timeout) { PRFileDesc *real_fd = NULL; PRIntervalTime timeout_interval = (PRIntervalTime)(timeout % UINT32_MAX); jobject result = NULL; int read_amount = 0; uint8_t *buffer = NULL; PR_ASSERT(env != NULL && fd != NULL && amount >= 0 && flags >= 0 && timeout >= 0 && timeout <= UINT32_MAX); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return NULL; } PR_ASSERT(real_fd != NULL); buffer = calloc(amount, sizeof(uint8_t)); read_amount = PR_Recv(real_fd, buffer, amount, flags, timeout_interval); if (read_amount <= 0) { goto done; } result = JSS_ToByteArray(env, buffer, read_amount); done: free(buffer); return result; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_PR_Send(JNIEnv *env, jclass clazz, jobject fd, jbyteArray buf, jint flags, jlong timeout) { PRFileDesc *real_fd = NULL; int max_length = 0; uint8_t *buffer = NULL; PRIntervalTime timeout_interval = (PRIntervalTime)(timeout % UINT32_MAX); int result = 0; PR_ASSERT(env != NULL && fd != NULL && buf != NULL && flags >= 0 && timeout >= 0 && timeout <= UINT32_MAX); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return 0; } PR_ASSERT(real_fd != NULL); max_length = (*env)->GetArrayLength(env, buf); buffer = (uint8_t*)((*env)->GetByteArrayElements(env, buf, NULL)); if (buffer == NULL) { return 0; } result = PR_Send(real_fd, buffer, max_length, flags, timeout_interval); (*env)->ReleaseByteArrayElements(env, buf, (jbyte *)buffer, JNI_ABORT); return result; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_PR_GetError(JNIEnv *env, jclass clazz) { return PR_GetError(); } JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_nss_PR_GetErrorTextNative(JNIEnv *env, jclass clazz) { ssize_t error_size; char *error_text = NULL; jbyteArray result = NULL; PR_ASSERT(env != NULL); error_size = PR_GetErrorTextLength(); if (error_size < 0) { return NULL; } error_text = calloc(error_size + 1, sizeof(char)); if (PR_GetErrorText(error_text) == 0) { free(error_text); return NULL; } result = JSS_ToByteArray(env, error_text, error_size); free(error_text); return result; } JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_nss_PR_ErrorToNameNative(JNIEnv *env, jclass clazz, jint error_code) { size_t error_size; const char *error_name = NULL; jbyteArray result = NULL; PR_ASSERT(env != NULL); error_name = PR_ErrorToName(error_code); if (error_name == NULL) { return NULL; } error_size = strlen(error_name); result = JSS_ToByteArray(env, error_name, error_size); return result; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_PR_getPRShutdownRcv(JNIEnv *env, jclass clazz) { return PR_SHUTDOWN_RCV; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_PR_getPRShutdownSend(JNIEnv *env, jclass clazz) { return PR_SHUTDOWN_SEND; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_PR_getPRShutdownBoth(JNIEnv *env, jclass clazz) { return PR_SHUTDOWN_BOTH; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_PR_getPRSuccess(JNIEnv *env, jclass clazz) { return PR_SUCCESS; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_PR_getPRFailure(JNIEnv *env, jclass clazz) { return PR_FAILURE; } jss-5.0.0/src/main/java/org/mozilla/jss/nss/PR.java000066400000000000000000000132641412550063600220030ustar00rootroot00000000000000package org.mozilla.jss.nss; /** * This class provides static access to raw NSPS calls with the PR prefix, * and handles the usage of NativeProxy objects. */ public class PR { /** * Shut down the receiving side of the TCP connection. * * See also: Shutdown */ public static final int SHUTDOWN_RCV = getPRShutdownRcv(); /** * Shut down the sending side of the TCP connection. * * See also: Shutdown */ public static final int SHUTDOWN_SEND = getPRShutdownSend(); /** * Shut down both sides of the TCP connection. * * See also: Shutdown */ public static final int SHUTDOWN_BOTH = getPRShutdownBoth(); /** * Return value on success from NSPR functions. * * See also: PR_SUCCESS in /usr/include/nspr4/prtypes.h */ public static final int SUCCESS = getPRSuccess(); /** * Return value on failure from NSPR functions. * * See also: PR_FAILURE in /usr/include/nspr4/prtypes.h */ public static final int FAILURE = getPRFailure(); /** * Open the file at name (with the specified flags and mode) and create * a new PRFDProxy (to a NSPR PRFileDesc *) for that file. * * See also: PR_Open in /usr/include/nspr4/prio.h */ public static native PRFDProxy Open(String name, int flags, int mode); /** * Open a new TCP Socket and create a new PRFDProxy for that socket. * * See also: PR_NewTCPSocket in /usr/include/nspr4/prio.h */ public static native PRFDProxy NewTCPSocket(); /** * Create a new j_buffer backed PRFileDesc, mimicing a TCP socket with * the specified peer_info. * * See also: newBufferPRFileDesc in org/mozilla/jss/ssl/javax/BufferPRFD.h */ public static native PRFDProxy NewBufferPRFD(BufferProxy read_buf, BufferProxy write_buf, byte[] peer_info); /** * Close an existing PRFDProxy, clearing the pointer if successful. * * See also: PR_Close in /usr/include/nspr4/prio.h */ public static int Close(PRFDProxy fd) { if (fd == null || fd.isNull()) { return SUCCESS; } return Close(fd, true); } /** * Close an existing PRFDProxy with an option to clear the pointer. * * See also: PR_Close in /usr/include/nspr4/prio.h */ public static native int Close(PRFDProxy fd, boolean clear); /** * Close an existing SSLFDProxy. * * See also: org.mozilla.jss.nss.PR.Close * org.mozilla.jss.nss.SSLFDProxy.releaseNativeResources */ public synchronized static int Close(SSLFDProxy fd) throws Exception { if (fd == null || fd.isNull()) { return SUCCESS; } // Because a SSLFDProxy instance needs to free other native resources, // we can't release the pointer here. Instead, let NativeProxy.close() // handle clearing the PRFileDesc pointer. return Close((PRFDProxy) fd, false); } /** * Shutdown an existing PRFDProxy. * This is usually used with TCP modes. * * See also: PR_Shutdown in /usr/include/nspr4/prio.h */ public static native int Shutdown(PRFDProxy fd, int how); /** * Read up to amount bytes from a PRFDProxy. * * See also: PR_Read in /usr/include/nspr4/prio.h */ public static native byte[] Read(PRFDProxy fd, int amount); /** * Recv up to amount bytes from a PRFDProxy, given the specified receive * flags and timeout value. * * See also: PR_Recv in /usr/include/nspr4/prio.h */ public static native byte[] Recv(PRFDProxy fd, int amount, int flags, long timeout); /** * Write the specified bytes to the PRFDProxy. * * Note: Unlike PR_Write, this method assumes the entire buffer is being * written. * * See also: PR_Write in /usr/include/nspr4/prio.h */ public static native int Write(PRFDProxy fd, byte[] buf); /** * Send the specified bytes via the PRFDProxy, given the specified * send flags and timeout value. * * See also: PR_Send in /usr/include/nspr4/prio.h */ public static native int Send(PRFDProxy fd, byte[] buf, int flags, long timeout); /** * Get the value of the current PR error. This is cleared on each NSPR * call. * * See also: PR_GetError in /usr/include/nspr4/prio.h */ public static native int GetError(); /** * Get the error text of the current PR error. This is cleared on each * NSPR call. * * See also: PR_GetErrorText in /usr/include/nspr4/prio.h */ public static String GetErrorText() { byte[] text = GetErrorTextNative(); if (text == null) { return ""; } return new String(text); } private static native byte[] GetErrorTextNative(); /** * Get the constant name of the current PR error. This is cleared on each * NSPR call. * * See also: PR_ErrorToName in /usr/include/nspr4/prio.h */ public static String ErrorToName(int code) { byte[] name = ErrorToNameNative(code); if (name == null) { return ""; } return new String(name); } private static native byte[] ErrorToNameNative(int code); /* Internal methods for querying constants. */ private static native int getPRShutdownRcv(); private static native int getPRShutdownSend(); private static native int getPRShutdownBoth(); private static native int getPRSuccess(); private static native int getPRFailure(); } jss-5.0.0/src/main/java/org/mozilla/jss/nss/PRErrors.c000066400000000000000000000007711412550063600225000ustar00rootroot00000000000000#include #include #include #include #include "jssutil.h" #include "PRFDProxy.h" #include "BufferProxy.h" #include "BufferPRFD.h" #include "_jni/org_mozilla_jss_nss_PRErrors.h" JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_PRErrors_getWouldBlockError(JNIEnv *env, jclass clazz) { return PR_WOULD_BLOCK_ERROR; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_PRErrors_getSocketShutdownError(JNIEnv *env, jclass clazz) { return PR_SOCKET_SHUTDOWN_ERROR; } jss-5.0.0/src/main/java/org/mozilla/jss/nss/PRErrors.java000066400000000000000000000014141412550063600231720ustar00rootroot00000000000000package org.mozilla.jss.nss; /** * This class provides access to useful NSPR errors, getting their values from * a JNI call. Note that it *isn't* an enum as the NSPR wrappers return int. * This saves us from having to wrap every NSPR error. */ public class PRErrors { /** * The call would block. * * See also: PR_WOULD_BLOCK_ERROR in /usr/include/nspr4/prerr.h */ public static final int WOULD_BLOCK_ERROR = getWouldBlockError(); /** * The socket is shutdown. * * See also: PR_SOCKET_SHUTDOWN_ERROR in /usr/include/nspr4/prerr.h */ public static final int SOCKET_SHUTDOWN_ERROR = getSocketShutdownError(); private static native int getWouldBlockError(); private static native int getSocketShutdownError(); } jss-5.0.0/src/main/java/org/mozilla/jss/nss/PRFDProxy.c000066400000000000000000000031601412550063600225520ustar00rootroot00000000000000#include #include #include "java_ids.h" #include "jssutil.h" #include "PRFDProxy.h" static jobject JSS_PR_wrapFDProxy(JNIEnv *env, PRFileDesc **fd, const char *className, const char *conSig) { jbyteArray pointer = NULL; jclass proxyClass; jmethodID constructor; jobject fdObj = NULL; PR_ASSERT(env != NULL && fd != NULL && *fd != NULL); /* convert pointer to byte array */ pointer = JSS_ptrToByteArray(env, *fd); /* Lookup the class and constructor */ proxyClass = (*env)->FindClass(env, className); if(proxyClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } constructor = (*env)->GetMethodID(env, proxyClass, PLAIN_CONSTRUCTOR, conSig); if(constructor == NULL) { ASSERT_OUTOFMEM(env); goto finish; } /* call the constructor */ fdObj = (*env)->NewObject(env, proxyClass, constructor, pointer); finish: if (fdObj == NULL && *fd != NULL) { /* didn't work, so free resources */ PR_Close(*fd); } *fd = NULL; PR_ASSERT(fdObj || (*env)->ExceptionOccurred(env)); return fdObj; } jobject JSS_PR_wrapPRFDProxy(JNIEnv *env, PRFileDesc **fd) { return JSS_PR_wrapFDProxy(env, fd, PRFD_PROXY_CLASS_NAME, PRFD_PROXY_CONSTRUCTOR_SIG); } jobject JSS_PR_wrapSSLFDProxy(JNIEnv *env, PRFileDesc **fd) { return JSS_PR_wrapFDProxy(env, fd, SSLFD_PROXY_CLASS_NAME, SSLFD_PROXY_CONSTRUCTOR_SIG); } PRStatus JSS_PR_getPRFileDesc(JNIEnv *env, jobject prfd_proxy, PRFileDesc **fd) { return JSS_getPtrFromProxy(env, prfd_proxy, (void**)fd); } jss-5.0.0/src/main/java/org/mozilla/jss/nss/PRFDProxy.h000066400000000000000000000007471412550063600225670ustar00rootroot00000000000000#include #include #pragma once /* Wrap a C/NSPR PRFileDesc into a Java PRFDProxy, closing the fd on error. */ jobject JSS_PR_wrapPRFDProxy(JNIEnv *env, PRFileDesc **fd); /* Wrap a C/NSPR PRFileDesc into a Java SSLFDProxy, closing the fd on error. */ jobject JSS_PR_wrapSSLFDProxy(JNIEnv *env, PRFileDesc **fd); /* Extract the C/NSPR PRFileDesc from an instance of a Java PRFDProxy. */ PRStatus JSS_PR_getPRFileDesc(JNIEnv *env, jobject prfd_proxy, PRFileDesc **fd); jss-5.0.0/src/main/java/org/mozilla/jss/nss/PRFDProxy.java000066400000000000000000000005631412550063600232550ustar00rootroot00000000000000package org.mozilla.jss.nss; public class PRFDProxy extends org.mozilla.jss.util.NativeProxy { public PRFDProxy(byte[] pointer) { super(pointer); } @Override protected void releaseNativeResources() throws Exception { PR.Close(this); } @Override protected void finalize() throws Throwable { super.finalize(); } } jss-5.0.0/src/main/java/org/mozilla/jss/nss/SECErrors.c000066400000000000000000000024251412550063600225670ustar00rootroot00000000000000#include #include #include #include #include #include #include #include "jssutil.h" #include "PRFDProxy.h" #include "BufferProxy.h" #include "BufferPRFD.h" #include "_jni/org_mozilla_jss_nss_SECErrors.h" JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SECErrors_getBadDER(JNIEnv *env, jclass clazz) { return SEC_ERROR_BAD_DER; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SECErrors_getExpiredCertificate(JNIEnv *env, jclass clazz) { return SEC_ERROR_EXPIRED_CERTIFICATE; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SECErrors_getCertNotValid(JNIEnv *env, jclass clazz) { return SEC_ERROR_CERT_NOT_VALID; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SECErrors_getRevokedCertificateOCSP(JNIEnv *env, jclass clazz) { return SEC_ERROR_REVOKED_CERTIFICATE_OCSP; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SECErrors_getRevokedCertificate(JNIEnv *env, jclass clazz) { return SEC_ERROR_REVOKED_CERTIFICATE; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SECErrors_getUntrustedIssuer(JNIEnv *env, jclass clazz) { return SEC_ERROR_UNTRUSTED_ISSUER; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SECErrors_getUntrustedCert(JNIEnv *env, jclass clazz) { return SEC_ERROR_UNTRUSTED_CERT; } jss-5.0.0/src/main/java/org/mozilla/jss/nss/SECErrors.java000066400000000000000000000042261412550063600232670ustar00rootroot00000000000000package org.mozilla.jss.nss; /** * This class provides access to useful NSS errors, getting their values from * a JNI call. Note that it *isn't* an enum as the NSS wrappers return int. * This saves us from having to wrap every NSS error in a class instance only * to later unwrap it to make any useful calls. */ public class SECErrors { /** * Improperly encoded DER message. * * See also: SEC_ERROR_BAD_DER in /usr/include/nss3/secerr.h */ public static final int BAD_DER = getBadDER(); /** * Expired Certificate. * * See also: SEC_ERROR_EXPIRED_CERTIFICATE in /usr/include/nss3/secerr.h */ public static final int EXPIRED_CERTIFICATE = getExpiredCertificate(); /** * Certificate valid start date is in the future. * * See also: SEC_ERROR_CERT_NOT_VALID in /usr/include/nss3/secerr.h */ public static final int CERT_NOT_VALID = getCertNotValid(); /** * Certificate was revoked by the OCSP responder. * * See also: SEC_ERROR_REVOKED_CERTIFICATE_OCSP in /usr/include/nss3/secerr.h */ public static final int REVOKED_CERTIFICATE_OCSP = getRevokedCertificateOCSP(); /** * Certificate was revoked by the issuer. * * See also: SEC_ERROR_REVOKED_CERTIFICATE in /usr/include/nss3/secerr.h */ public static final int REVOKED_CERTIFICATE = getRevokedCertificate(); /** * Certificate was signed by an untrusted issuer. * * See also: SEC_ERROR_UNTRUSTED_ISSUER in /usr/include/nss3/secerr.h */ public static final int UNTRUSTED_ISSUER = getUntrustedIssuer(); /** * Certificate was marked as untrusted. * * See also: SEC_ERROR_UNTRUSTED_CERT in /usr/include/nss3/secerr.h */ public static final int UNTRUSTED_CERT = getUntrustedCert(); private static native int getBadDER(); private static native int getExpiredCertificate(); private static native int getCertNotValid(); private static native int getRevokedCertificateOCSP(); private static native int getRevokedCertificate(); private static native int getUntrustedIssuer(); private static native int getUntrustedCert(); } jss-5.0.0/src/main/java/org/mozilla/jss/nss/SSL.c000066400000000000000000000727011412550063600214250ustar00rootroot00000000000000#include #include #include #include #include #include #include #include #include "jssconfig.h" #include "jssl.h" #include "java_ids.h" #include "jss_exceptions.h" #include "jssutil.h" #include "pk11util.h" #include "PRFDProxy.h" #include "SSLFDProxy.h" #include "SSLVersionRange.h" #include "_jni/org_mozilla_jss_nss_SSL.h" jobject JSS_NewSecurityStatusResult(JNIEnv *env, int on, char *cipher, int keySize, int secretKeySize, char *issuer, char *subject) { jclass resultClass; jmethodID constructor; jobject result = NULL; jbyteArray cipher_java = NULL; jbyteArray issuer_java = NULL; jbyteArray subject_java = NULL; PR_ASSERT(env != NULL); resultClass = (*env)->FindClass(env, SECURITY_STATUS_CLASS_NAME); if (resultClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } constructor = (*env)->GetMethodID(env, resultClass, PLAIN_CONSTRUCTOR, SECURITY_STATUS_CONSTRUCTOR_SIG); if (constructor == NULL) { ASSERT_OUTOFMEM(env); goto finish; } if (cipher) { cipher_java = JSS_ToByteArray(env, cipher, strlen(cipher)); } if (issuer) { issuer_java = JSS_ToByteArray(env, issuer, strlen(issuer)); } if (subject) { subject_java = JSS_ToByteArray(env, subject, strlen(subject)); } result = (*env)->NewObject(env, resultClass, constructor, on, cipher_java, keySize, secretKeySize, issuer_java, subject_java); finish: PORT_Free(cipher); PORT_Free(issuer); PORT_Free(subject); return result; } jobject JSS_NewSSLChannelInfo(JNIEnv *env, jint protocolVersion, jint cipherSuite, jint authKeyBits, jint keaKeyBits, jlong creationTime, jlong lastAccessTime, jlong expirationTime, jbyteArray sessionID, jint compressionMethod, jboolean extendedMasterSecretUsed, jboolean earlyDataAccepted, jint keaType, jint keaGroup, jint symCipher, jint macAlgorithm, jint authType, jint signatureScheme, jboolean haveNSS334, jint originalKeaGroup, jboolean resumed, jboolean haveNSS345, jboolean peerDelegCred) { jclass resultClass; jmethodID constructor; jobject result = NULL; PR_ASSERT(env != NULL); resultClass = (*env)->FindClass(env, SSL_CHANNEL_INFO_CLASS_NAME); if (resultClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } constructor = (*env)->GetMethodID(env, resultClass, PLAIN_CONSTRUCTOR, SSL_CHANNEL_INFO_CONSTRUCTOR_SIG); if (constructor == NULL) { ASSERT_OUTOFMEM(env); goto finish; } result = (*env)->NewObject(env, resultClass, constructor, protocolVersion, cipherSuite, authKeyBits, keaKeyBits, creationTime, lastAccessTime, expirationTime, sessionID, compressionMethod, extendedMasterSecretUsed, earlyDataAccepted, keaType, keaGroup, symCipher, macAlgorithm, authType, signatureScheme, haveNSS334, originalKeaGroup, resumed, haveNSS345, peerDelegCred); finish: return result; } jobject JSS_NewSSLPreliminaryChannelInfo(JNIEnv *env, jlong valuesSet, jint protocolVersion, jint cipherSuite, jboolean canSendEarlyData, jlong maxEarlyDataSize, jboolean haveNSS343, jint zeroRttCipherSuite, jboolean haveNSS348, jboolean peerDelegCred, jint authKeyBits, jint signatureScheme) { jclass resultClass; jmethodID constructor; jobject result = NULL; PR_ASSERT(env != NULL); resultClass = (*env)->FindClass(env, SSL_PRELIMINARY_CHANNEL_INFO_CLASS_NAME); if (resultClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } constructor = (*env)->GetMethodID(env, resultClass, PLAIN_CONSTRUCTOR, SSL_PRELIMINARY_CHANNEL_INFO_CONSTRUCTOR_SIG); if (constructor == NULL) { ASSERT_OUTOFMEM(env); goto finish; } result = (*env)->NewObject(env, resultClass, constructor, valuesSet, protocolVersion, cipherSuite, canSendEarlyData, maxEarlyDataSize, haveNSS343, zeroRttCipherSuite, haveNSS348, peerDelegCred, authKeyBits, signatureScheme); finish: return result; } JNIEXPORT jobject JNICALL Java_org_mozilla_jss_nss_SSL_ImportFD(JNIEnv *env, jclass clazz, jobject model, jobject fd) { PR_ASSERT(0); JSS_throwMsg(env, NULL_POINTER_EXCEPTION, "JSS JAR/DLL version mismatch"); return NULL; } JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_nss_SSL_ImportFDNative(JNIEnv *env, jclass clazz, jobject model, jobject fd) { PRFileDesc *result = NULL; PRFileDesc *real_model = NULL; PRFileDesc *real_fd = NULL; PR_ASSERT(env != NULL); PR_SetError(0, 0); /* Note: NSS calling semantics state that either model or fd can be * NULL; so when the Java Object is not-NULL, dereference it. */ if (model != NULL && (JSS_PR_getPRFileDesc(env, model, &real_model) != PR_SUCCESS || real_model == NULL)) { return NULL; } if (fd != NULL && (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS || real_fd == NULL)) { return NULL; } result = SSL_ImportFD(real_model, real_fd); if (result == NULL) { return NULL; } return JSS_ptrToByteArray(env, result); } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SSL_OptionSet(JNIEnv *env, jclass clazz, jobject fd, jint option, jint val) { PRFileDesc *real_fd = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return SECFailure; } return SSL_OptionSet(real_fd, option, val); } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SSL_OptionGet(JNIEnv *env, jclass clazz, jobject fd, jint option) { PRFileDesc *real_fd = NULL; int result = -1; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { JSS_throwMsg(env, INVALID_PARAMETER_EXCEPTION, "Unable to dereference fd object"); return result; } if (SSL_OptionGet(real_fd, option, &result) != SECSuccess) { JSS_throwMsg(env, ILLEGAL_ARGUMENT_EXCEPTION, "Unknown option to get or getting option failed"); } return result; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SSL_SetURL(JNIEnv *env, jclass clazz, jobject fd, jstring url) { PRFileDesc *real_fd = NULL; SECStatus ret = SECFailure; const char *real_url = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return ret; } real_url = JSS_RefJString(env, url); if (real_url == NULL) { return ret; } ret = SSL_SetURL(real_fd, real_url); JSS_DerefJString(env, url, real_url); return ret; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SSL_CipherPrefSet(JNIEnv *env, jclass clazz, jobject fd, jint cipher, jboolean enabled) { PRFileDesc *real_fd = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return SECFailure; } return SSL_CipherPrefSet(real_fd, cipher, enabled); } JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_nss_SSL_CipherPrefGet(JNIEnv *env, jclass clazz, jobject fd, jint cipher) { PRFileDesc *real_fd = NULL; int enabled = false; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { JSS_throwMsg(env, INVALID_PARAMETER_EXCEPTION, "Unable to dereference fd object"); return enabled; } if (SSL_CipherPrefGet(real_fd, cipher, &enabled) != SECSuccess) { JSS_throwMsg(env, ILLEGAL_ARGUMENT_EXCEPTION, "Unknown cipher suite to get or getting its value failed"); return enabled; } return enabled; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SSL_CipherPrefSetDefault(JNIEnv *env, jclass clazz, jint cipher, jboolean enabled) { PR_ASSERT(env != NULL); PR_SetError(0, 0); return SSL_CipherPrefSetDefault(cipher, enabled); } JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_nss_SSL_CipherPrefGetDefault(JNIEnv *env, jclass clazz, jint cipher) { int enabled = false; PR_ASSERT(env != NULL); PR_SetError(0, 0); if (SSL_CipherPrefGetDefault(cipher, &enabled) != SECSuccess) { JSS_throwMsg(env, ILLEGAL_ARGUMENT_EXCEPTION, "Unknown cipher suite to get or getting its value failed"); return enabled; } return enabled; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SSL_VersionRangeSetNative(JNIEnv *env, jclass clazz, jobject fd, jint min_ssl, jint max_ssl) { PRFileDesc *real_fd = NULL; SSLVersionRange vrange; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (min_ssl < 0 || min_ssl >= JSSL_enums_size || max_ssl < 0 || max_ssl >= JSSL_enums_size) { char buf[128]; snprintf(buf, 128, "SSL.VersionRangeSetNative(): for min=%d max=%d failed - out of range for array JSSL_enums size: %d", min_ssl, max_ssl, JSSL_enums_size); JSSL_throwSSLSocketException(env, buf); return SECFailure; } if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { JSS_throwMsg(env, INVALID_PARAMETER_EXCEPTION, "Unable to dereference fd object"); return SECFailure; } vrange.min = JSSL_enums[min_ssl]; vrange.max = JSSL_enums[max_ssl]; return SSL_VersionRangeSet(real_fd, &vrange); } JNIEXPORT jobject JNICALL Java_org_mozilla_jss_nss_SSL_VersionRangeGet(JNIEnv *env, jclass clazz, jobject fd) { PRFileDesc *real_fd = NULL; SSLVersionRange vrange; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { JSS_throwMsg(env, INVALID_PARAMETER_EXCEPTION, "Unable to dereference fd object"); return NULL; } if (SSL_VersionRangeGet(real_fd, &vrange) != SECSuccess) { JSS_throwMsg(env, INVALID_PARAMETER_EXCEPTION, "Unable to dereference fd object"); return NULL; } return JSS_SSL_wrapVersionRange(env, vrange); } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SSL_VersionRangeSetDefaultNative(JNIEnv *env, jclass clazz, jint variant_ssl, jint min_ssl, jint max_ssl) { SSLVersionRange vrange; SSLProtocolVariant variant; PR_ASSERT(env != NULL); PR_SetError(0, 0); if (min_ssl < 0 || min_ssl >= JSSL_enums_size || max_ssl < 0 || max_ssl >= JSSL_enums_size || variant_ssl < 0 || variant_ssl >= JSSL_enums_size) { char buf[200]; snprintf(buf, 200, "SSL.VersionRangeSetDefaultNative(): for min=%d max=%d " "variant=%d failed - out of range for array JSSL_enums " "size: %d", min_ssl, max_ssl, variant_ssl, JSSL_enums_size); JSSL_throwSSLSocketException(env, buf); return SECFailure; } vrange.min = JSSL_enums[min_ssl]; vrange.max = JSSL_enums[max_ssl]; variant = JSSL_enums[variant_ssl]; return SSL_VersionRangeSetDefault(variant, &vrange); } JNIEXPORT jobject JNICALL Java_org_mozilla_jss_nss_SSL_VersionRangeGetDefaultNative(JNIEnv *env, jclass clazz, jint variant_ssl) { SSLVersionRange vrange; SSLProtocolVariant variant; PR_SetError(0, 0); if (variant_ssl < 0 || variant_ssl >= JSSL_enums_size) { char buf[200]; snprintf(buf, 200, "SSL.VersionRangeGetDefaultNative(): for variant=%d failed: " "out of range for array JSSL_enums size: %d", variant_ssl, JSSL_enums_size); JSSL_throwSSLSocketException(env, buf); return NULL; } variant = JSSL_enums[variant_ssl]; if (SSL_VersionRangeGetDefault(variant, &vrange) != SECSuccess) { JSS_throwMsg(env, INVALID_PARAMETER_EXCEPTION, "Unable to inquire default SSL version for this protocol"); return NULL; } return JSS_SSL_wrapVersionRange(env, vrange); } JNIEXPORT jobject JNICALL Java_org_mozilla_jss_nss_SSL_SecurityStatus(JNIEnv *env, jclass clazz, jobject fd) { PRFileDesc *real_fd = NULL; int on; char *cipher; int keySize; int secretKeySize; char *issuer; char *subject; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return NULL; } if (SSL_SecurityStatus(real_fd, &on, &cipher, &keySize, &secretKeySize, &issuer, &subject) != SECSuccess) { return NULL; } return JSS_NewSecurityStatusResult(env, on, cipher, keySize, secretKeySize, issuer, subject); } JNIEXPORT jobject JNICALL Java_org_mozilla_jss_nss_SSL_GetChannelInfo(JNIEnv *env, jclass clazz, jobject fd) { PRFileDesc *real_fd = NULL; SSLChannelInfo info = { 0 }; jint pV = 0; jint cS = 0; jint aKB = 0; jint kKB = 0; jlong cT = 0; jlong lAT = 0; jlong eT = 0; jbyteArray sID = NULL; jint cM = 0; jboolean eMSU = JNI_FALSE; jboolean eDA = JNI_FALSE; jint kT = 0; jint kG = 0; jint sC = 0; jint mA = 0; jint aT = 0; jint sS = 0; jboolean haveNSS334 = JNI_FALSE; jint oKG = 0; jboolean r = JNI_FALSE; jboolean haveNSS345 = JNI_FALSE; jboolean pDC = JNI_FALSE; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return NULL; } if (SSL_GetChannelInfo(real_fd, &info, sizeof(info)) != SECSuccess) { return NULL; } pV = JSSL_enums_reverse(info.protocolVersion); cS = info.cipherSuite; aKB = info.authKeyBits; kKB = info.keaKeyBits; cT = info.creationTime; lAT = info.lastAccessTime; eT = info.expirationTime; sID = JSS_ToByteArray(env, info.sessionID, info.sessionIDLength); cM = info.compressionMethod; eMSU = info.extendedMasterSecretUsed; eDA = info.earlyDataAccepted; kT = info.keaType; kG = info.keaGroup; sC = info.symCipher; mA = info.macAlgorithm; aT = info.authType; sS = info.signatureScheme; #ifdef HAVE_NSS_CHANNEL_INFO_ORIGINAL_KEA_GROUP /* The following fields were added in NSS v3.34 and are detected * via feature detection in CMake. */ haveNSS334 = JNI_TRUE; oKG = info.originalKeaGroup; r = info.resumed; #endif #ifdef HAVE_NSS_CHANNEL_INFO_PEER_DELEG_CRED /* The following fields were added in NSS v3.45 and are detected * via feature detection in CMake. */ haveNSS345 = JNI_TRUE; pDC = info.peerDelegCred; #endif return JSS_NewSSLChannelInfo(env, pV, cS, aKB, kKB, cT, lAT, eT, sID, cM, eMSU, eDA, kT, kG, sC, mA, aT, sS, haveNSS334, oKG, r, haveNSS345, pDC); } JNIEXPORT jobject JNICALL Java_org_mozilla_jss_nss_SSL_GetPreliminaryChannelInfo(JNIEnv *env, jclass clazz, jobject fd) { PRFileDesc *real_fd = NULL; SSLPreliminaryChannelInfo info = { 0 }; jlong vS = 0; jint pV = 0; jint cS = 0; jboolean cSED = JNI_FALSE; jlong mEDS = 0; jboolean haveNSS343 = JNI_FALSE; jint zRCS = 0; jboolean haveNSS348 = JNI_FALSE; jboolean pDC = JNI_FALSE; jint aKB = 0; jint sS = 0; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return NULL; } if (SSL_GetPreliminaryChannelInfo(real_fd, &info, sizeof(info)) != SECSuccess) { return NULL; } vS = info.valuesSet; pV = JSSL_enums_reverse(info.protocolVersion); cS = info.cipherSuite; cSED = info.canSendEarlyData; mEDS = info.maxEarlyDataSize; #ifdef HAVE_NSS_PRELIMINARY_CHANNEL_INFO_ZERO_RTT_CIPHER_SUITE /* The following fields were added in NSS v3.43 and are detected * via feature detection in CMake. */ haveNSS343 = JNI_TRUE; zRCS = info.zeroRttCipherSuite; #endif #ifdef HAVE_NSS_PRELIMINARY_CHANNEL_INFO_PEER_DELEG_CRED /* The following fields were added in NSS v3.48 and are detected * via feature detection in CMake. */ haveNSS348 = JNI_TRUE; pDC = info.peerDelegCred; aKB = info.authKeyBits; sS = info.signatureScheme; #endif return JSS_NewSSLPreliminaryChannelInfo(env, vS, pV, cS, cSED, mEDS, haveNSS343, zRCS, haveNSS348, pDC, aKB, sS); } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SSL_ResetHandshake(JNIEnv *env, jclass clazz, jobject fd, jboolean asServer) { PRFileDesc *real_fd = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return SECFailure; } return SSL_ResetHandshake(real_fd, asServer); } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SSL_ReHandshake(JNIEnv *env, jclass clazz, jobject fd, jboolean flushCache) { PRFileDesc *real_fd = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return SECFailure; } return SSL_ReHandshake(real_fd, flushCache); } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SSL_ForceHandshake(JNIEnv *env, jclass clazz, jobject fd) { PRFileDesc *real_fd = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return SECFailure; } return SSL_ForceHandshake(real_fd); } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SSL_ConfigSecureServer(JNIEnv *env, jclass clazz, jobject fd, jobject cert, jobject key, jint kea) { PRFileDesc *real_fd = NULL; CERTCertificate *real_cert = NULL; SECKEYPrivateKey *real_key = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return SECFailure; } if (JSS_PK11_getCertPtr(env, cert, &real_cert) != PR_SUCCESS) { return SECFailure; } if (JSS_PK11_getPrivKeyPtr(env, key, &real_key) != PR_SUCCESS) { return SECFailure; } return SSL_ConfigSecureServer(real_fd, real_cert, real_key, kea); } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SSL_ConfigServerCert(JNIEnv *env, jclass clazz, jobject fd, jobject cert, jobject key) { PRFileDesc *real_fd = NULL; CERTCertificate *real_cert = NULL; SECKEYPrivateKey *real_key = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return SECFailure; } if (JSS_PK11_getCertPtr(env, cert, &real_cert) != PR_SUCCESS) { return SECFailure; } if (JSS_PK11_getPrivKeyPtr(env, key, &real_key) != PR_SUCCESS) { return SECFailure; } return SSL_ConfigServerCert(real_fd, real_cert, real_key, NULL, 0); } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SSL_ConfigServerSessionIDCache(JNIEnv *env, jclass clazz, jint maxCacheEntries, jlong timeout, jlong ssl3_timeout, jstring directory) { const char *dir_path; SECStatus ret = SECFailure; PR_ASSERT(env != NULL); PR_SetError(0, 0); dir_path = JSS_RefJString(env, directory); ret = SSL_ConfigServerSessionIDCache(maxCacheEntries, timeout, ssl3_timeout, dir_path); JSS_DerefJString(env, directory, dir_path); return ret; } JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SSL_InvalidateSession(JNIEnv *env, jclass clazz, jobject fd) { PRFileDesc *real_fd = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return SECFailure; } return SSL_InvalidateSession(real_fd); } JNIEXPORT jobject JNICALL Java_org_mozilla_jss_nss_SSL_PeerCertificate(JNIEnv *env, jclass clazz, jobject fd) { PRFileDesc *real_fd = NULL; CERTCertificate *cert = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return NULL; } cert = SSL_PeerCertificate(real_fd); if (cert == NULL) { return NULL; } return JSS_PK11_wrapCert(env, &cert); } JNIEXPORT jobjectArray JNICALL Java_org_mozilla_jss_nss_SSL_PeerCertificateChain(JNIEnv *env, jclass clazz, jobject fd) { PRFileDesc *real_fd = NULL; CERTCertList *chain = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return NULL; } chain = SSL_PeerCertificateChain(real_fd); int error = PORT_GetError(); if (chain == NULL && error == SSL_ERROR_NO_CERTIFICATE) { return NULL; } else if (chain == NULL /* && error != SSL_ERROR_NO_CERTIFICATE */) { JSS_throwMsgPrErrArg(env, SECURITY_EXCEPTION, "Unable to construct peer certificate chain.", error); return NULL; } return JSS_PK11_wrapCertChain(env, &chain); } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_SendCertificateRequest(JNIEnv *env, jclass clazz, jobject fd) { PRFileDesc *real_fd = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return SECFailure; } return SSL_SendCertificateRequest(real_fd); } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_KeyUpdate(JNIEnv *env, jclass clazz, jobject fd, jboolean requestUpdate) { PRFileDesc *real_fd = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return SECFailure; } return SSL_KeyUpdate(real_fd, requestUpdate == JNI_TRUE ? PR_TRUE : PR_FALSE); } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_AttachClientCertCallback(JNIEnv *env, jclass clazz, jobject fd) { PRFileDesc *real_fd = NULL; CERTCertificate *real_cert = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return SECFailure; } if (JSS_NSS_getSSLClientCert(env, fd, &real_cert) != PR_SUCCESS) { return SECFailure; } /* When the returned cert is empty and no error occurred, there was no * client certificate specified via SSLFD.SetClientCert(...). Don't add * the certificate selection callback handler. */ if (real_cert == NULL) { return SECSuccess; } return SSL_GetClientAuthDataHook(real_fd, JSSL_SSLFDCertSelectionCallback, (void *)real_cert); } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_EnableAlertLoggingNative(JNIEnv *env, jclass clazz, jobject fd) { PRFileDesc *real_fd = NULL; jobject fd_ref = NULL; SECStatus ret = SECFailure; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return ret; } if (JSS_NSS_getGlobalRef(env, fd, &fd_ref) != PR_SUCCESS) { return ret; } ret = SSL_AlertReceivedCallback(real_fd, JSSL_SSLFDAlertReceivedCallback, fd_ref); if (ret != SECSuccess) { return ret; } ret = SSL_AlertSentCallback(real_fd, JSSL_SSLFDAlertSentCallback, fd_ref); return ret; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_ConfigJSSDefaultCertAuthCallback(JNIEnv *env, jclass clazz, jobject fd) { PRFileDesc *real_fd = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return SECFailure; } return SSL_AuthCertificateHook(real_fd, JSSL_DefaultCertAuthCallback, NULL); } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_ConfigAsyncTrustManagerCertAuthCallback(JNIEnv *env, jclass clazz, jobject fd) { PRFileDesc *real_fd = NULL; jobject fd_ref = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return SECFailure; } if (JSS_NSS_getGlobalRef(env, fd, &fd_ref) != PR_SUCCESS) { return SECFailure; } return SSL_AuthCertificateHook(real_fd, JSSL_SSLFDAsyncCertAuthCallback, fd_ref); } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_ConfigSyncTrustManagerCertAuthCallback(JNIEnv *env, jclass clazz, jobject fd) { PRFileDesc *real_fd = NULL; jobject fd_ref = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return SECFailure; } if (JSS_NSS_getGlobalRef(env, fd, &fd_ref) != PR_SUCCESS) { return SECFailure; } return SSL_AuthCertificateHook(real_fd, JSSL_SSLFDSyncCertAuthCallback, fd_ref); } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_ConfigAsyncBadCertCallback(JNIEnv *env, jclass clazz, jobject fd) { PRFileDesc *real_fd = NULL; jobject fd_ref = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return SECFailure; } if (JSS_NSS_getGlobalRef(env, fd, &fd_ref) != PR_SUCCESS) { return SECFailure; } return SSL_BadCertHook(real_fd, JSSL_SSLFDAsyncBadCertCallback, fd_ref); } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_ConfigSyncBadCertCallback(JNIEnv *env, jclass clazz, jobject fd) { PRFileDesc *real_fd = NULL; jobject fd_ref = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return SECFailure; } if (JSS_NSS_getGlobalRef(env, fd, &fd_ref) != PR_SUCCESS) { return SECFailure; } return SSL_BadCertHook(real_fd, JSSL_SSLFDSyncBadCertCallback, fd_ref); } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_AuthCertificateComplete(JNIEnv *env, jclass clazz, jobject fd, jint error) { PRFileDesc *real_fd = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return SECFailure; } return SSL_AuthCertificateComplete(real_fd, error); } JNIEXPORT void JNICALL Java_org_mozilla_jss_nss_SSL_RemoveCallbacks(JNIEnv *env, jclass clazz, jobject fd) { PRFileDesc *real_fd = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return; } SSL_AlertReceivedCallback(real_fd, NULL, NULL); SSL_AlertSentCallback(real_fd, NULL, NULL); SSL_AuthCertificateHook(real_fd, NULL, NULL); } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_EnableHandshakeCallback(JNIEnv *env, jclass clazz, jobject fd) { PRFileDesc *real_fd = NULL; jobject fd_ref = NULL; PR_ASSERT(env != NULL && fd != NULL); PR_SetError(0, 0); if (JSS_PR_getPRFileDesc(env, fd, &real_fd) != PR_SUCCESS) { return SECFailure; } if (JSS_NSS_getGlobalRef(env, fd, &fd_ref) != PR_SUCCESS) { return SECFailure; } return SSL_HandshakeCallback(real_fd, JSSL_SSLFDHandshakeComplete, fd_ref); } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_getSSLRequestCertificate(JNIEnv *env, jclass clazz) { return SSL_REQUEST_CERTIFICATE; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_getSSLRequireCertificate(JNIEnv *env, jclass clazz) { return SSL_REQUIRE_CERTIFICATE; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_getSSLSECSuccess(JNIEnv *env, jclass clazz) { return SECSuccess; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_getSSLSECFailure(JNIEnv *env, jclass clazz) { return SECFailure; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_getSSLSECWouldBlock(JNIEnv *env, jclass clazz) { return SECWouldBlock; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_getSSLEnablePostHandshakeAuth(JNIEnv *env, jclass clazz) { return SSL_ENABLE_POST_HANDSHAKE_AUTH; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_getSSLEnableRenegotiation(JNIEnv *env, jclass clazz) { return SSL_ENABLE_RENEGOTIATION; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_getSSLRequireSafeNegotiation(JNIEnv *env, jclass clazz) { return SSL_REQUIRE_SAFE_NEGOTIATION; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_getSSLRenegotiateNever(JNIEnv *env, jclass clazz) { return SSL_RENEGOTIATE_NEVER; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_getSSLRenegotiateUnrestricted(JNIEnv *env, jclass clazz) { return SSL_RENEGOTIATE_UNRESTRICTED; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_getSSLRenegotiateRequiresXtn(JNIEnv *env, jclass clazz) { return SSL_RENEGOTIATE_REQUIRES_XTN; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_getSSLRenegotiateTransitional(JNIEnv *env, jclass clazz) { return SSL_RENEGOTIATE_TRANSITIONAL; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_getSSLEnableFallbackSCSV(JNIEnv *env, jclass clazz) { return SSL_ENABLE_FALLBACK_SCSV; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_getSSLRequireNever(JNIEnv *env, jclass clazz) { return SSL_REQUIRE_NEVER; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_getSSLRequireAlways(JNIEnv *env, jclass clazz) { return SSL_REQUIRE_ALWAYS; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_getSSLRequireFirstHandshake(JNIEnv *env, jclass clazz) { return SSL_REQUIRE_FIRST_HANDSHAKE; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_nss_SSL_getSSLRequireNoError(JNIEnv *env, jclass clazz) { return SSL_REQUIRE_NO_ERROR; } jss-5.0.0/src/main/java/org/mozilla/jss/nss/SSL.java000066400000000000000000000473561412550063600221340ustar00rootroot00000000000000package org.mozilla.jss.nss; /** * This class provides static access to raw NSS calls with the SSL prefix, * and handles the usage of NativeProxy objects. */ import java.util.ArrayList; import org.mozilla.jss.pkcs11.PK11Cert; import org.mozilla.jss.pkcs11.PK11PrivKey; import org.mozilla.jss.ssl.SSLAlertEvent; import org.mozilla.jss.ssl.SSLProtocolVariant; import org.mozilla.jss.ssl.SSLVersionRange; public class SSL { /** * Request certificate from the remote peer. Value for use with OptionGet * and OptionSet. * * See also: SSL_REQUEST_CERTIFICATE in /usr/include/nss3/ssl.h */ public static final int REQUEST_CERTIFICATE = getSSLRequestCertificate(); /** * Require certificate from the remote peer. Value for use with OptionGet * and OptionSet. * * See also: SSL_REQUIRE_CERTIFICATE in /usr/include/nss3/ssl.h */ public static final int REQUIRE_CERTIFICATE = getSSLRequireCertificate(); /** * Return value on success from NSS functions. * * See also: SECSuccess in /usr/include/nss3/seccomon.h */ public static final int SECSuccess = getSSLSECSuccess(); /** * Return value on failure from NSS functions. * * See also: SECFailure in /usr/include/nss3/seccomon.h */ public static final int SECFailure = getSSLSECFailure(); /** * Return value from NSS functions when the operation would block. * * See also: SECWouldBlock in /usr/include/nss3/seccomon.h */ public static final int SECWouldBlock = getSSLSECWouldBlock(); /** * Enable post-handshake authentication extension. Value for use with * OptionGet. * * See also: SSL_ENABLE_POST_HANDSHAKE_AUTH in /usr/include/nss3/ssl.h */ public static final int ENABLE_POST_HANDSHAKE_AUTH = getSSLEnablePostHandshakeAuth(); /** * Option for configuring renegotiation after initial handshake. Value for * use with OptionGet and OptionSet. * * See also: SSL_ENABLE_RENEGOTIATION in /usr/include/nss3/ssl.h */ public static final int ENABLE_RENEGOTIATION = getSSLEnableRenegotiation(); /** * Option for requiring safe negotiation. Value for use with OptionGet and * OptionSet. * * See also: SSL_REQUIRE_SAFE_NEGOTIATION in /usr/include/nss3/ssl.h */ public static final int REQUIRE_SAFE_NEGOTIATION = getSSLRequireSafeNegotiation(); /** * Value for never allowing renegotiation after initial handshake. Value * for use with ENABLE_RENEGOTIATION with OptionGet and OptionSet. * * See also: SSL_RENEGOTIATE_NEVER in /usr/include/nss3/ssl.h */ public static final int RENEGOTIATE_NEVER = getSSLRenegotiateNever(); /** * Value for always allowing renegotiation after initial handshake, * regardless of whether or not the peer's client hellow bears the * renegotiation info extension; unsafe. Value for use with * ENABLE_RENEGOTIATION with OptionGet and OptionSet. * * See also: SSL_RENEGOTIATE_UNRESTRICTED in /usr/include/nss3/ssl.h */ public static final int RENEGOTIATE_UNRESTRICTED = getSSLRenegotiateUnrestricted(); /** * Value for allowing renegotiation after initial handshake with the TLS * renegotiation_info extension; safe. Value for use with * ENABLE_RENEGOTIATION with OptionGet and OptionSet. * * See also: SSL_RENEGOTIATE_REQUIRES_XTN in /usr/include/nss3/ssl.h */ public static final int RENEGOTIATE_REQUIRES_XTN = getSSLRenegotiateRequiresXtn(); /** * Value for disallowing unsafe renegotiation in server sockets only, but * allows clients to continue to renegotiate with vulnerable servers. * Value for use with ENABLE_RENEGOTIATION with OptionGet and OptionSet. * * See also: SSL_RENEGOTIATE_TRANSITIONAL in /usr/include/nss3/ssl.h */ public static final int RENEGOTIATE_TRANSITIONAL = getSSLRenegotiateTransitional(); /** * Option for sending SCSV in handshakes. Value for use with OptionGet and * OptionSet. * * See also: SSL_ENABLE_FALLBACK_SCSV in /usr/include/nss3/ssl.h */ public static final int ENABLE_FALLBACK_SCSV = getSSLEnableFallbackSCSV(); /** * Value for never requiring a certificate. Value for use with * SSL_REQUIRE_CERTIFICATE with OptionGet and OptionSet. * * See also: SSL_REQUIRE_NEVER in /usr/include/nss3/ssl.h */ public static final int REQUIRE_NEVER = getSSLRequireNever(); /** * Value for always requiring a certificate. Value for use with * SSL_REQUIRE_CERTIFICATE with OptionGet and OptionSet. * * See also: SSL_REQUIRE_ALWAYS in /usr/include/nss3/ssl.h */ public static final int REQUIRE_ALWAYS = getSSLRequireAlways(); /** * Value for requiring a certificate only on the first handshake. Value * for use with SSL_REQUIRE_CERTIFICATE with OptionGet and OptionSet. * * See also: SSL_REQUIRE_FIRST_HANDSHAKE in /usr/include/nss3/ssl.h */ public static final int REQUIRE_FIRST_HANDSHAKE = getSSLRequireFirstHandshake(); /** * Value for requiring a certificate but not erring if the peer doesn't * provide one. Value for use with SSL_REQUIRE_CERTIFICATE with OptionGet * and OptionSet. * * See also: SSL_REQUIRE_NO_ERROR in /usr/include/nss3/ssl.h */ public static final int REQUIRE_NO_ERROR = getSSLRequireNoError(); /** * Import a file descriptor to create a new SSL file descriptor out of it. * * See also: SSL_ImportFD in /usr/include/nss3/ssl.h */ public static SSLFDProxy ImportFD(PRFDProxy model, PRFDProxy fd) { if (fd == null) { throw new NullPointerException("Expected fd != null"); } byte[] ptr = ImportFDNative(model, fd); if (ptr == null || ptr.length == 0) { int error = PR.GetError(); throw new NullPointerException("SSL_ImportFD failed: " + PR.ErrorToName(error) + " (" + error + ")"); } fd.clear(); return new SSLFDProxy(ptr); } public static native byte[] ImportFDNative(PRFDProxy model, PRFDProxy fd); /** * Set the value of a SSL option on the specified PRFileDesc. * * See also: SSL_OptionSet in /usr/include/nss3/ssl.h */ public static native int OptionSet(SSLFDProxy fd, int option, int val); /** * Get the value of a SSL option on the specified PRFileDesc. Note that * this raises an exception in the case of an invalid option. * * See also: SSL_OptionGet in /usr/include/nss3/ssl.h */ public static native int OptionGet(SSLFDProxy fd, int option) throws Exception; /** * Set the hostname of a handshake on the specified PRFileDesc. * * See also: SSL_SetURL in /usr/include/nss3/ssl.h */ public static native int SetURL(SSLFDProxy fd, String url); /** * Set the preference for a specific cipher suite on the specified * PRFileDesc. * * See also: SSL_CipherPrefSet in /usr/include/nss3/ssl.h */ public static native int CipherPrefSet(SSLFDProxy fd, int cipher, boolean enabled); /** * Get the preference for a specific cipher suite on the specified * PRFileDesc. Note that this can raise an Exception when the cipher * is unknown. * * See also: SSL_CipherPrefGet in /usr/include/nss3/ssl.h */ public static native boolean CipherPrefGet(SSLFDProxy fd, int cipher) throws Exception; /** * Set the default preferences for a specific cipher suite across all * future PRFileDesc's. * * See also: SSL_CipherPrefSetDefault in /usr/include/nss3/ssl.h */ public static native int CipherPrefSetDefault(int cipher, boolean enabled); /** * Get the default preferences for a specific cipher suite across all * future PRFileDesc's. Note that this can raise an Exception when the * cipher is unknown. * * See also: SSL_CipherPrefGetDefault in /usr/include/nss3/ssl.h */ public static native boolean CipherPrefGetDefault(int cipher); /** * Set the range of TLS versions enabled by this server by SSLVersionRange. * * See also: SSL_VersionRangeSet in /usr/include/nss3/ssl.h */ public static int VersionRangeSet(SSLFDProxy fd, SSLVersionRange range) { return VersionRangeSetNative(fd, range.getMinEnum(), range.getMaxEnum()); } /** * Set the range of TLS versions enabled by this server. The integer * parameters are values of the SSLVersion enum. * * See also: SSL_VersionRangeSet in /usr/include/nss3/ssl.h */ private static native int VersionRangeSetNative(SSLFDProxy fd, int min_ssl, int max_ssl); /** * Get the range of TLS versions enabled by this server. * * See also: SSL_VersionRangeSet in /usr/include/nss3/ssl.h */ public static native SSLVersionRange VersionRangeGet(SSLFDProxy fd) throws Exception; /** * Set the range of TLS versions enabled by default, for all future * PRFileDesc's of the default protocol variant type, STREAM. * * See also: SSL_VersionRangeSetDefault in /usr/include/nss3/ssl.h */ public static int VersionRangeSetDefault(SSLVersionRange range) { return VersionRangeSetDefault(SSLProtocolVariant.STREAM, range); } /** * Set the range of TLS versions enabled by default, for all future * PRFileDesc's of the specified protocol variant. * * See also: SSL_VersionRangeSetDefault in /usr/include/nss3/ssl.h */ public static int VersionRangeSetDefault(SSLProtocolVariant variant, SSLVersionRange range) { return VersionRangeSetDefaultNative(variant.getEnum(), range.getMinEnum(), range.getMaxEnum()); } /** * Set the range of default TLS versions enabled in all future * PRFileDesc's. The integer parameters are values of the SSLVersion enum. * * See also: SSL_VersionRangeSet in /usr/include/nss3/ssl.h */ private static native int VersionRangeSetDefaultNative(int variant_ssl, int min_ssl, int max_ssl); /** * Get the range of TLS versions enabled in all future PRFileDesc's of the * default STREAM protocol variant.. * * See also: SSL_VersionRangeGetDefault in /usr/include/nss3/ssl.h */ public static SSLVersionRange VersionRangeGetDefault() { return VersionRangeGetDefault(SSLProtocolVariant.STREAM); } /** * Get the range of TLS versions enabled in all future PRFileDesc's of the * specified protocol variant. * * See also: SSL_VersionRangeGetDefault in /usr/include/nss3/ssl.h */ public static SSLVersionRange VersionRangeGetDefault(SSLProtocolVariant variant) { return VersionRangeGetDefaultNative(variant.getEnum()); } private static native SSLVersionRange VersionRangeGetDefaultNative(int variant); /** * Check the security status of a SSL handshake. * * See also: SSL_SecurityStatus in /usr/include/nss3/ssl.h */ public static native SecurityStatusResult SecurityStatus(SSLFDProxy fd); /** * Inquire for SSL Channel Information after the handshake has completed. * * See also: SSL_GetChannelInfo in /usr/include/nss3/ssl.h */ public static native SSLChannelInfo GetChannelInfo(SSLFDProxy fd); /** * Inquire for SSL Channel Information before the handshake has completed. * * See also: SSL_GetPreliminaryChannelInfo in /usr/include/nss3/ssl.h */ public static native SSLPreliminaryChannelInfo GetPreliminaryChannelInfo(SSLFDProxy fd); /** * Reset the handshake status, optionally handshaking as a server. * * See also: SSL_ResetHandshake in /usr/include/nss3/ssl.h */ public static native int ResetHandshake(SSLFDProxy fd, boolean asServer); /** * Rehandshake an existing socket, optionally flushing the cache line. * * See also: SSL_ReHandshake in /usr/include/nss3/ssl.h */ public static native int ReHandshake(SSLFDProxy fd, boolean flushCache); /** * Force a handshake to occur if not started, else step one. * * See also: SSL_ForceHandshake in /usr/include/nss3/ssl.h */ public static native int ForceHandshake(SSLFDProxy fd); /** * Configure the certificate and private key for a server socket. * * @deprecated replaced with ConfigServerCert * See also: SSL_ConfigSecureServer in /usr/include/nss3/ssl.h */ @Deprecated public static native int ConfigSecureServer(SSLFDProxy fd, PK11Cert cert, PK11PrivKey key, int kea); /** * Configure the certificate and private key for a server socket. This * form assumes no additional data is passed. * * See also: SSL_ConfigServerCert in /usr/include/nss3/ssl.h */ public static native int ConfigServerCert(SSLFDProxy fd, PK11Cert cert, PK11PrivKey key); /** * Configure the server's session cache. * * See also: SSL_ConfigServerSessionIDCache in /usr/include/nss3/ssl.h */ public synchronized static native int ConfigServerSessionIDCache(int maxCacheEntries, long timeout, long ssl3_timeout, String directory); /** * Invalidate the SSL session associated with this socket. * * See also: SSL_InvalidateSession in /usr/include/nss3/ssl.h */ public static native int InvalidateSession(SSLFDProxy fd); /** * Introspect the peer's certificate. * * See also: SSL_PeerCertificate in /usr/include/nss3/ssl.h */ public static native PK11Cert PeerCertificate(SSLFDProxy fd); /** * Introspect the peer's certificate chain. * * See also: SSL_PeerCertificateChain in /usr/include/nss3/ssl.h */ public static native PK11Cert[] PeerCertificateChain(SSLFDProxy fd) throws Exception; /** * Send the TLS 1.3 Certificate Request as a server; experimental. * * See also: SSL_SendCertificateRequest in /usr/include/nss3/sslexp.h */ public static native int SendCertificateRequest(SSLFDProxy fd); /** * Send the TLS 1.3 KeyUpdate Request; experimental. * * See also: SSL_KeyUpdate in /usr/include/nss3/sslexp.h */ public static native int KeyUpdate(SSLFDProxy fd, boolean requestUpdate); /** * Use client authentication; set client certificate from SSLFDProxy. * * See also: SSL_GetClientAuthDataHook in /usr/include/nss3/ssl.h, * org.mozilla.jss.nss.SSLFDProxy.SetClientCert(...) */ public static native int AttachClientCertCallback(SSLFDProxy fd); /** * Enable recording of alerts in the SSLFDProxy object. * * See also: SSL_AlertReceivedCallback in /usr/include/nss3/ssl.h, * SSL_AlertSentCallback in /usr/include/nss3/ssl.h */ public static int EnableAlertLogging(SSLFDProxy fd) { fd.inboundAlerts = new ArrayList(); fd.inboundOffset = 0; fd.outboundAlerts = new ArrayList(); fd.outboundOffset = 0; return EnableAlertLoggingNative(fd); } /* Internal helper for EnableAlertLogging method. */ private static native int EnableAlertLoggingNative(SSLFDProxy fd); /** * Use the default JSS certificate checking handler (which understands * CryptoManager OCSP status). * * See also: SSL_AuthCertificateHook in /usr/include/nss3/ssl.h and * JSSL_DefaultCertAuthCallback in jss/ssl/callbacks.c */ public static native int ConfigJSSDefaultCertAuthCallback(SSLFDProxy fd); /** * Use an asynchronous certificate checking handler which allows us to * invoke an arbitrary number of TrustManagers. This makes functions like * SSL_ForceHandshake, PR_Read, and PR_Write return back to the caller * when cert auth is required. We set the SSLFDProxy.needCertValidation * field to true in this case. Set this field to false and call * SSL_AuthCertificateComplete with the status code of the error (0 if * the cert is valid), and resume handshaking. * * See also: SSL_AuthCertificateHook in /usr/include/nss3/ssl.h and * JSSL_SSLFDAsyncCertAuthCallback in jss/nss/SSLFDProxy.c */ public static native int ConfigAsyncTrustManagerCertAuthCallback(SSLFDProxy fd); /** * Use a synchronous certificate checking handler based off the SSLFDProxy * proper. This allows us to invoke an arbitrary number of TrustManagers, * but with the caveat that it needs to be synchronous and respond via the * auth callback hook. This should only be called on the server side of * the connection, because it doesn't support the superior async method. * * See also: SSL_AuthCertificateHook in /usr/include/nss3/ssl.h and * JSSL_SSLFDSyncCertAuthCallback in jss/nss/SSLFDProxy.c */ public static native int ConfigSyncTrustManagerCertAuthCallback(SSLFDProxy fd); /** * Use an asynchronous bad certificate handler which allows us to approve * rejected certificates. This allows us to bypass the hostname check * failure caused by the Java socket having no knowledge of the hostname * we use for certificate validation; no HostnameVerifier is passed in. * As a result, NSS has no value for the hostname and validation will fail. * * Note: This does NOT work for server-side connections. * * See also: SSL_BadCertHook in /usr/include/nss3/ssl.h and * JSSL_SSLFDAsyncBadCertCallback in jss/nss/SSLFDProxy.c */ public static native int ConfigAsyncBadCertCallback(SSLFDProxy fd); /** * Use a synchronous bad certificate handler which allows us to approve * rejected certificates. This allows us to bypass the hostname check * failure caused by the Java socket having no knowledge of the hostname * we use for certificate validation; no HostnameVerifier is passed in. * As a result, NSS has no value for the hostname and validation will fail. * * See also: SSL_BadCertHook in /usr/include/nss3/ssl.h and * JSSL_SSLFDSyncBadCertCallback in jss/nss/SSLFDProxy.c */ public static native int ConfigSyncBadCertCallback(SSLFDProxy fd); /** * Inform NSS that the asynchronous certificate check handler has * completed, allowing us to continue the handshake. * * This is also used for the async bad certificate handler as well. * * See also: SSL_AuthCertificateComplete in /usr/include/nss3/ssl.h */ public static native int AuthCertificateComplete(SSLFDProxy fd, int error); /** * Removes all enabled callbacks. */ public static native void RemoveCallbacks(SSLFDProxy fd); /* * Enable handshake completion status checking. * * See also: SSL_HandshakeCallback in /usr/include/nss3/ssl.h */ public static native int EnableHandshakeCallback(SSLFDProxy fd); /* Internal methods for querying constants. */ private static native int getSSLRequestCertificate(); private static native int getSSLRequireCertificate(); private static native int getSSLSECSuccess(); private static native int getSSLSECFailure(); private static native int getSSLSECWouldBlock(); private static native int getSSLEnablePostHandshakeAuth(); private static native int getSSLEnableRenegotiation(); private static native int getSSLRequireSafeNegotiation(); private static native int getSSLRenegotiateNever(); private static native int getSSLRenegotiateUnrestricted(); private static native int getSSLRenegotiateRequiresXtn(); private static native int getSSLRenegotiateTransitional(); private static native int getSSLEnableFallbackSCSV(); private static native int getSSLRequireNever(); private static native int getSSLRequireAlways(); private static native int getSSLRequireFirstHandshake(); private static native int getSSLRequireNoError(); } jss-5.0.0/src/main/java/org/mozilla/jss/nss/SSLChannelInfo.java000066400000000000000000000352451412550063600242330ustar00rootroot00000000000000package org.mozilla.jss.nss; import java.lang.StringBuilder; import org.mozilla.jss.crypto.ObjectNotFoundException; import org.mozilla.jss.ssl.*; import org.mozilla.jss.netscape.security.util.Utils; /** * Class representing the SSLChannelInfo struct from NSS's sslt.h. * * This class is a data class; it contains public getters and no * setters. It usually should be constructed via a call to * org.mozilla.jss.nss.SSL.GetChannelInfo(SSLFDProxy inst) rather than * directly constructing an instance. * * Note that calling GetChannelInfo prior to the handshake completing on * the socket usually won't work or will give incomplete or inconclusive * results. Use SSL.GetPreliminaryChannelInfo instead and see the * corresponding class, SSLPreliminaryChannelInfo. * * Field and getter names match that in the NSS equivalent struct. The only * omitted field is sessionIDLength, since sessionID.length suffices and Java * byte arrays are of fixed, known length. */ public class SSLChannelInfo { /** * Which protocol version is used by this SSL socket. */ private SSLVersion protocolVersion; /** * Which cipher suite is used by this SSL socket. */ private SSLCipher cipherSuite; /** * How many bits are in the authentication key. * * NSS describes this as follows: * * The strength of the key used to authenticate the peer. Before * interpreting this value, check authType, signatureScheme, and * peerDelegCred, to determine the type of the key and how it was used. * * Typically, this is the length of the key from the peer's end-entity * certificate. If delegated credentials are used (i.e., peerDelegCred is * PR_TRUE), then this is the strength of the delegated credential key. */ private int authKeyBits; /** * How many bits are in the key exchange key. * * NSS describes this as follows: * * key exchange algorithm info */ private int keaKeyBits; /** * When the session was created, in seconds since Jan 1, 1970. */ private long creationTime; /** * When the session was last accessed, in seconds since Jan 1, 1970. */ private long lastAccessTime; /** * When the session expires, in seconds since Jan 1, 1970. */ private long expirationTime; /** * Identifier for this session. * * Up to 32 bytes. */ private byte[] sessionID; /** * Compression method used in this session. * * This field was added in NSS 3.12.5. */ private SSLCompressionMethod compressionMethod; /** * Whether or not an extended master secret was used for TLS versions less * than 1.3. * * This field was added in NSS 3.21. */ private boolean extendedMasterSecretUsed; /** * Whether or not early data was accepted. * * This field was added in NSS 3.25. * * NSS has this to say: * * This field only has meaning in TLS versions greater than or equal to * 1.3, and indicates on the client side that the server accepted early * (0-RTT) data. */ private boolean earlyDataAccepted; /** * Key exchange algorithm info. * * This field has the same meaning as in SSLCipherSuiteInfo. * * This field was added in NSS 3.28. */ private SSLKEAType keaType; /** * When keaType is an EC-based cipher, name of the group used in this * cipher. * * This field has the same meaning as in SSLCipherSuiteInfo. * * This field was added in NSS 3.28. */ private SSLNamedGroup keaGroup; /** * Symmetric cipher algorithm info. * * This field has the same meaning as in SSLCipherSuiteInfo. * * This field was added in NSS 3.28. */ private SSLCipherAlgorithm symCipher; /** * MAC algorithm info. * * This field has the same meaning as in SSLCipherSuiteInfo. * * This field was added in NSS 3.28. * * NSS gives the following description of this field in * SSLCipherSuiteInfo: * * AEAD ciphers don't have a MAC. For an AEAD cipher, macAlgorithmName * is "AEAD", macAlgorithm is ssl_mac_aead, and macBits is the length in * bits of the authentication tag. */ private SSLMACAlgorithm macAlgorithm; /** * Authentication type for the cipher suite. * * This field has the same meaning as in SSLCipherSuiteInfo. * * This field was added in NSS 3.28. * * NSS gives the following description of this field in * SSLCipherSuiteInfo: * * This reports the correct authentication type for the cipher suite, use * this instead of |authAlgorithm|. */ private SSLAuthType authType; /** * Signature scheme used. * * This field was added in NSS 3.28. */ private SSLSignatureScheme signatureScheme; /** * This field controls whether or not we have the following two fields: * * - originalKeaGroup, and * - resumed. * * When this field is true, the values of these fields can be trusted. * Otherwise, their values should be ignored. * * The corresponding fields are present when the NSS version used to * compile JSS and the runtime version of NSS match, and both have these * fields. */ private boolean haveNSS334; /** * This field holds the key exchange algorithm group during the initial * handshake. * * This field was added in NSS 3.34. * * NSS has the following description of this field: * * When the session was resumed this holds the key exchange group of the * original handshake. */ private SSLNamedGroup originalKeaGroup; /** * Whether or not this session was resumed. * * This field was added in NSS 3.34. */ private boolean resumed; /** * This field controls whether or not we have the peerDelegCred field. * * When this field is true, the values of these fields can be trusted. * Otherwise, their values should be ignored. * * The corresponding fields are present when the NSS version used to * compile JSS and the runtime version of NSS match, and both have these * fields. */ private boolean haveNSS345; /** * Whether or not the peer used a delegated credential for authentication. * * This field was added in NSS 3.45. */ private boolean peerDelegCred; /** * Constructor used by SSL.GetChannelInfo(...). * * This translates between ints and enum constants. */ public SSLChannelInfo(int protocolVersion, int cipherSuite, int authKeyBits, int keaKeyBits, long creationTime, long lastAccessTime, long expirationTime, byte[] sessionID, int compressionMethod, boolean extendedMasterSecretUsed, boolean earlyDataAccepted, int keaType, int keaGroup, int symCipher, int macAlgorithm, int authType, int signatureScheme, boolean haveNSS334, int originalKeaGroup, boolean resumed, boolean haveNSS345, boolean peerDelegCred) { try { this.protocolVersion = SSLVersion.valueOf(protocolVersion); } catch (IllegalArgumentException iae) { this.protocolVersion = null; } this.cipherSuite = SSLCipher.valueOf(cipherSuite); this.authKeyBits = authKeyBits; this.keaKeyBits = keaKeyBits; this.creationTime = creationTime; this.lastAccessTime = lastAccessTime; this.expirationTime = expirationTime; this.sessionID = sessionID; this.compressionMethod = SSLCompressionMethod.valueOf(compressionMethod); this.extendedMasterSecretUsed = extendedMasterSecretUsed; this.earlyDataAccepted = earlyDataAccepted; this.keaType = SSLKEAType.valueOf(keaType); this.keaGroup = SSLNamedGroup.valueOf(keaGroup); this.symCipher = SSLCipherAlgorithm.valueOf(symCipher); this.macAlgorithm = SSLMACAlgorithm.valueOf(macAlgorithm); this.authType = SSLAuthType.valueOf(authType); this.signatureScheme = SSLSignatureScheme.valueOf(signatureScheme); this.haveNSS334 = haveNSS334; if (haveNSS334) { this.originalKeaGroup = SSLNamedGroup.valueOf(originalKeaGroup); this.resumed = resumed; } this.haveNSS345 = haveNSS345; if (haveNSS345) { this.peerDelegCred = peerDelegCred; } } /** * Gets the value of protocolVersion. * * See also: protocolVersion */ public SSLVersion getProtocolVersion() { return protocolVersion; } /** * Gets the value of cipherSuite. * * See also: cipherSuite. */ public SSLCipher getCipherSuite() { return cipherSuite; } /** * Gets the value of authKeyBits. * * See also: authKeyBits. */ public int getAuthKeyBits() { return authKeyBits; } /** * Gets the value of keaKeyBits. * * See also: keaKeyBits. */ public int getKeaKeyBits() { return keaKeyBits; } /** * Gets the value of creationTime. * * See also: creationTime. */ public long getCreationTime() { return creationTime; } /** * Gets the value of lastAccessTime. * * See also: lastAccessTime. */ public long getLastAccessTime() { return lastAccessTime; } /** * Gets the value of expirationTime. * * See also: expirationTime. */ public long getExpirationTime() { return expirationTime; } /** * Gets the value of sessionID. * * See also: sessionID. */ public byte[] getSessionID() { return sessionID; } /** * Gets the value of compressionMethod. * * See also: compressionMethod. */ public SSLCompressionMethod getCompressionMethod() { return compressionMethod; } /** * Gets the value of extendedMasterSecretUsed. * * See also: extendedMasterSecretUsed. */ public boolean getExtendedMasterSecretUsed() { return extendedMasterSecretUsed; } /** * Gets the value of earlyDataAccepted. * * See also: earlyDataAccepted. */ public boolean getEarlyDataAccepted() { return earlyDataAccepted; } /** * Gets the value of keaType. * * See also: keaType. */ public SSLKEAType getKeaType() { return keaType; } /** * Gets the value of keaGroup. * * See also: keaGroup. */ public SSLNamedGroup getKeaGroup() { return keaGroup; } /** * Gets the value of symCipher. * * See also: symCipher. */ public SSLCipherAlgorithm getSymCipher() { return symCipher; } /** * Gets the value of macAlgorithm. * * See also: macAlgorithm. */ public SSLMACAlgorithm getMacAlgorithm() { return macAlgorithm; } /** * Gets the value of authType. * * See also: authType. */ public SSLAuthType getAuthType() { return authType; } /** * Gets the value of signatureScheme. * * See also: signatureScheme. */ public SSLSignatureScheme getSignatureScheme() { return signatureScheme; } /** * Gets the value of originalKeaGroup; throws an exception when the * field isn't available from NSS. * * See also: originalKeaGroup. */ public SSLNamedGroup getOriginalKeaGroup() throws ObjectNotFoundException { if (!haveNSS334) { String msg = "The version of NSS used to compile JSS doesn't "; msg += "support this field in SSLChannelInfo. Either backport "; msg += "this feature or upgrade to at least NSS v3.34. Check "; msg += "the value of HAVE_NSS_CHANNEL_INFO_ORIGINAL_KEA_GROUP "; msg += "when building JSS."; throw new ObjectNotFoundException(msg); } return originalKeaGroup; } /** * Gets the value of resumed; throws an exception when the field isn't * available from NSS. * * See also: resumed. */ public boolean getResumed() throws ObjectNotFoundException { if (!haveNSS334) { String msg = "The version of NSS used to compile JSS doesn't "; msg += "support this field in SSLChannelInfo. Either backport "; msg += "this feature or upgrade to at least NSS v3.34. Check "; msg += "the value of HAVE_NSS_CHANNEL_INFO_ORIGINAL_KEA_GROUP "; msg += "when building JSS."; throw new ObjectNotFoundException(msg); } return resumed; } /** * Gets the value of peerDelegCred; throws an exception when the field * isn't available from NSS. * * See also: peerDelegCred. */ public boolean getPeerDelegCred() throws ObjectNotFoundException { if (!haveNSS345) { String msg = "The version of NSS used to compile JSS doesn't "; msg += "support this field in SSLChannelInfo. Either backport "; msg += "this feature or upgrade to at least NSS v3.45. Check "; msg += "the value of HAVE_NSS_CHANNEL_INFO_PEER_DELEG_CRED "; msg += "when building JSS."; throw new ObjectNotFoundException(msg); } return peerDelegCred; } /** * Returns a string representation of the data in this data structure. */ @Override public String toString() { StringBuilder result = new StringBuilder("SSLChannelInfo:"); result.append("\n- protocolVersion: " + protocolVersion); result.append("\n- cipherSuite: " + cipherSuite); result.append("\n- authKeyBits: " + authKeyBits); result.append("\n- keaKeyBits: " + keaKeyBits); result.append("\n- creationTime: " + creationTime); result.append("\n- lastAccessTime: " + lastAccessTime); result.append("\n- expirationTime: " + expirationTime); result.append("\n- sessionID: " + Utils.HexEncode(sessionID)); result.append("\n- compressionMethod: " + compressionMethod); result.append("\n- extendedMasterSecretUsed: " + extendedMasterSecretUsed); result.append("\n- earlyDataAccepted: " + earlyDataAccepted); result.append("\n- keaType: " + keaType); result.append("\n- keaGroup: " + keaGroup); result.append("\n- symCipher: " + symCipher); result.append("\n- macAlgorithm: " + macAlgorithm); result.append("\n- authType: " + authType); result.append("\n- signatureScheme: " + signatureScheme); if (haveNSS334) { result.append("\n- originalKeaGroup: " + originalKeaGroup); result.append("\n- resumed: " + resumed); result.append("\n- peerDelegCred: " + peerDelegCred); } return result.toString(); } } jss-5.0.0/src/main/java/org/mozilla/jss/nss/SSLErrors.c000066400000000000000000000006401412550063600226130ustar00rootroot00000000000000#include #include #include #include #include #include #include #include "jssutil.h" #include "PRFDProxy.h" #include "BufferProxy.h" #include "BufferPRFD.h" #include "_jni/org_mozilla_jss_nss_SECErrors.h" JNIEXPORT int JNICALL Java_org_mozilla_jss_nss_SSLErrors_getBadCertDomain(JNIEnv *env, jclass clazz) { return SSL_ERROR_BAD_CERT_DOMAIN; } jss-5.0.0/src/main/java/org/mozilla/jss/nss/SSLErrors.java000066400000000000000000000011021412550063600233040ustar00rootroot00000000000000package org.mozilla.jss.nss; /** * This class provides access to useful NSS/SSL errors, getting their values * from a JNI call. Note that it *isn't* an enum as the NSS wrappers return * int. This saves us from having to wrap every NSS error in a class instance * only to later unwrap it to make any useful calls. */ public class SSLErrors { /** * Certificate has a bad hostname. * * See also: in /usr/include/nss3/sslcerr.h */ public static final int BAD_CERT_DOMAIN = getBadCertDomain(); private static native int getBadCertDomain(); } jss-5.0.0/src/main/java/org/mozilla/jss/nss/SSLFDProxy.c000066400000000000000000000336341412550063600227030ustar00rootroot00000000000000#include #include #include #include #include #include #include "java_ids.h" #include "jssutil.h" #include "pk11util.h" #include "jss_exceptions.h" #include "SSLFDProxy.h" #include "GlobalRefProxy.h" PRStatus JSS_NSS_getSSLClientCert(JNIEnv *env, jobject sslfd_proxy, CERTCertificate **cert) { jclass sslfdProxyClass; jfieldID certField; jobject certProxy; PR_ASSERT(env != NULL && sslfd_proxy != NULL && cert != NULL); /* Resolve the clientCert field on a SSLFDProxy object. */ sslfdProxyClass = (*env)->GetObjectClass(env, sslfd_proxy); if (sslfdProxyClass == NULL) { return PR_FAILURE; } certField = (*env)->GetFieldID(env, sslfdProxyClass, SSLFD_PROXY_CLIENT_CERT_FIELD, SSLFD_PROXY_CLIENT_CERT_SIG); if (certField == NULL) { return PR_FAILURE; } certProxy = (*env)->GetObjectField(env, sslfd_proxy, certField); if (certProxy == NULL) { *cert = NULL; return PR_SUCCESS; } /* Get the underlying CERTCertificate pointer from the clientCert * (of type PK11Cert) object. */ return JSS_PK11_getCertPtr(env, certProxy, cert); } static PRStatus JSS_NSS_getEventArrayList(JNIEnv *env, jobject sslfd_proxy, const char *which, jobject *list) { jclass sslfdProxyClass; jfieldID eventArrayListField; PR_ASSERT(env != NULL && sslfd_proxy != NULL && list != NULL); sslfdProxyClass = (*env)->GetObjectClass(env, sslfd_proxy); if (sslfdProxyClass == NULL) { return PR_FAILURE; } eventArrayListField = (*env)->GetFieldID(env, sslfdProxyClass, which, SSLFD_PROXY_EVENT_LIST_SIG); if (eventArrayListField == NULL) { /* Unlike JSS_NSS_getSSLClientCert above, this is a failure to process * the event. We expect the */ return PR_FAILURE; } *list = (*env)->GetObjectField(env, sslfd_proxy, eventArrayListField); if (*list == NULL) { return PR_FAILURE; } return PR_SUCCESS; } PRStatus JSS_NSS_getSSLAlertReceivedList(JNIEnv *env, jobject sslfd_proxy, jobject *list) { return JSS_NSS_getEventArrayList(env, sslfd_proxy, "inboundAlerts", list); } PRStatus JSS_NSS_getSSLAlertSentList(JNIEnv *env, jobject sslfd_proxy, jobject *list) { return JSS_NSS_getEventArrayList(env, sslfd_proxy, "outboundAlerts", list); } PRStatus JSS_NSS_getGlobalRef(JNIEnv *env, jobject sslfd_proxy, jobject *global_ref) { PR_ASSERT(env != NULL && sslfd_proxy != NULL && global_ref != NULL); if (JSS_getPtrFromProxyOwner(env, sslfd_proxy, "globalRef", "L" GLOBAL_REF_PROXY_CLASS_NAME ";", (void **)global_ref) == PR_FAILURE || *global_ref == NULL) { JSS_throw(env, NULL_POINTER_EXCEPTION); return PR_FAILURE; } return PR_SUCCESS; } PRStatus JSS_NSS_addSSLAlert(JNIEnv *env, jobject sslfd_proxy, jobject list, const SSLAlert *alert) { jclass eventClass; jmethodID eventConstructor; jobject event; jclass eventListClass; jmethodID arrayListAdd; PR_ASSERT(env != NULL && sslfd_proxy != NULL && list != NULL && alert != NULL); /* Build the new alert event object (org.mozilla.jss.ssl.SSLAlertEvent). */ eventClass = (*env)->FindClass(env, SSL_ALERT_EVENT_CLASS); if (eventClass == NULL) { return PR_FAILURE; } eventConstructor = (*env)->GetMethodID(env, eventClass, "", "(L" SSLFD_PROXY_CLASS_NAME ";II)V"); if (eventConstructor == NULL) { return PR_FAILURE; } event = (*env)->NewObject(env, eventClass, eventConstructor, sslfd_proxy, (int)alert->level, (int)alert->description); if (event == NULL) { return PR_FAILURE; } /* Add it to the event list. */ eventListClass = (*env)->GetObjectClass(env, list); if (eventListClass == NULL) { return PR_FAILURE; } arrayListAdd = (*env)->GetMethodID(env, eventListClass, "add", "(Ljava/lang/Object;)Z"); if (arrayListAdd == NULL) { return PR_FAILURE; } // We ignore the return code: ArrayList.add() always returns true. (void)(*env)->CallBooleanMethod(env, list, arrayListAdd, event); return PR_SUCCESS; } void JSSL_SSLFDAlertReceivedCallback(const PRFileDesc *fd, void *arg, const SSLAlert *alert) { JNIEnv *env; jobject sslfd_proxy = (jobject)arg; jobject list; if (fd == NULL || arg == NULL || alert == NULL || JSS_javaVM == NULL) { return; } if ((*JSS_javaVM)->AttachCurrentThread(JSS_javaVM, (void**)&env, NULL) != JNI_OK || env == NULL) { return; } if (JSS_NSS_getSSLAlertReceivedList(env, sslfd_proxy, &list) != PR_SUCCESS) { return; } if (JSS_NSS_addSSLAlert(env, sslfd_proxy, list, alert) != PR_SUCCESS) { return; } } void JSSL_SSLFDAlertSentCallback(const PRFileDesc *fd, void *arg, const SSLAlert *alert) { JNIEnv *env; jobject sslfd_proxy = (jobject)arg; jobject list; if (fd == NULL || arg == NULL || alert == NULL || JSS_javaVM == NULL) { return; } if ((*JSS_javaVM)->AttachCurrentThread(JSS_javaVM, (void**)&env, NULL) != JNI_OK || env == NULL) { return; } if (JSS_NSS_getSSLAlertSentList(env, sslfd_proxy, &list) != PR_SUCCESS) { return; } if (JSS_NSS_addSSLAlert(env, sslfd_proxy, list, alert) != PR_SUCCESS) { return; } } SECStatus JSSL_SSLFDCertSelectionCallback(void *arg, PRFileDesc *fd, CERTDistNames *caNames, CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey) { CERTCertificate *cert = arg; PK11SlotList *slotList; PK11SlotListElement *slotElement; SECKEYPrivateKey *privkey = NULL; /* Certificate selection for client auth requires that we pass both the * certificate (in *pRetCert) and its key (in *pRetKey). We iterate over * all slots that the certificate is in, looking for a private key in * any of them. Once found, we return the private key. */ slotList = PK11_GetAllSlotsForCert(cert, NULL /* unused arg */); if (slotList == NULL) { return SECFailure; } for (slotElement = slotList->head; slotElement; slotElement = slotElement->next) { privkey = PK11_FindPrivateKeyFromCert(slotElement->slot, cert, NULL /* pinarg */); if (privkey != NULL) { break; } } /* Always free the slot list. */ PK11_FreeSlotList(slotList); /* If the certificate isn't found, return SECFailure. */ if (privkey == NULL) { return SECFailure; } *pRetCert = CERT_DupCertificate(cert); *pRetKey = privkey; return SECSuccess; } void JSSL_SSLFDHandshakeComplete(PRFileDesc *fd, void *client_data) { JNIEnv *env = NULL; jobject sslfd_proxy = (jobject)client_data; jclass sslfdProxyClass; jfieldID handshakeCompleteField; if (fd == NULL || client_data == NULL || JSS_javaVM == NULL) { return; } if ((*JSS_javaVM)->AttachCurrentThread(JSS_javaVM, (void**)&env, NULL) != JNI_OK || env == NULL) { return; } sslfdProxyClass = (*env)->GetObjectClass(env, sslfd_proxy); if (sslfdProxyClass == NULL) { return; } handshakeCompleteField = (*env)->GetFieldID(env, sslfdProxyClass, "handshakeComplete", "Z"); if (handshakeCompleteField == NULL) { return; } (*env)->SetBooleanField(env, sslfd_proxy, handshakeCompleteField, JNI_TRUE); } SECStatus JSSL_SSLFDAsyncCertAuthCallback(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer) { /* We know that arg is our GlobalRefProxy instance pointing to the * SSLFDProxy class instance. This lets us ignore the isServer parameter, * because we can infer that from our JSSEngine instance. Additionally, * because we have no control over whether or not our TrustManagers do * signature verification (we hope they do!) we ignore checkSig as well. * * All we need to do then is set SSLFDProxy@fd_ref's needCertValidation * to true. */ JNIEnv *env = NULL; jobject sslfd_proxy = (jobject) arg; jclass sslfdProxyClass; jfieldID needCertValidationField; if (arg == NULL || fd == NULL || JSS_javaVM == NULL) { return SECFailure; } if ((*JSS_javaVM)->AttachCurrentThread(JSS_javaVM, (void**)&env, NULL) != JNI_OK || env == NULL) { return SECFailure; } sslfdProxyClass = (*env)->GetObjectClass(env, sslfd_proxy); if (sslfdProxyClass == NULL) { return SECFailure; } needCertValidationField = (*env)->GetFieldID(env, sslfdProxyClass, "needCertValidation", "Z"); if (needCertValidationField == NULL) { return SECFailure; } (*env)->SetBooleanField(env, sslfd_proxy, needCertValidationField, JNI_TRUE); return SECWouldBlock; } SECStatus JSSL_SSLFDSyncCertAuthCallback(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer) { /* We know that arg is our GlobalRefProxy instance pointing to the * SSLFDProxy class instance. This lets us ignore the isServer parameter, * because we can infer that from our JSSEngine instance. Additionally, * because we have no control over whether or not our TrustManagers do * signature verification (we hope they do!) we ignore checkSig as well. * * All we need to do then is call SSLFDProxy@fd_ref's * invokeCertAuthHandler() method. */ JNIEnv *env = NULL; jobject sslfd_proxy = (jobject) arg; jclass sslfdProxyClass; jmethodID certAuthHandlerMethod; PRErrorCode ret; if (arg == NULL || fd == NULL || JSS_javaVM == NULL) { PR_SetError(SEC_ERROR_INVALID_ARGS, 0); return SECFailure; } if ((*JSS_javaVM)->AttachCurrentThread(JSS_javaVM, (void**)&env, NULL) != JNI_OK || env == NULL) { PR_SetError(PR_UNKNOWN_ERROR, 0); return SECFailure; } sslfdProxyClass = (*env)->GetObjectClass(env, sslfd_proxy); if (sslfdProxyClass == NULL) { PR_SetError(PR_UNKNOWN_ERROR, 0); return SECFailure; } certAuthHandlerMethod = (*env)->GetMethodID(env, sslfdProxyClass, "invokeCertAuthHandler", "()I"); if (certAuthHandlerMethod == NULL) { PR_SetError(PR_UNKNOWN_ERROR, 0); return SECFailure; } ret = (*env)->CallIntMethod(env, sslfd_proxy, certAuthHandlerMethod); if ((*env)->ExceptionOccurred(env) != NULL) { ret = PR_UNKNOWN_ERROR; } PR_SetError(ret, 0); if (ret == 0) { return SECSuccess; } return SECFailure; } SECStatus JSSL_SSLFDAsyncBadCertCallback(void *arg, PRFileDesc *fd) { /* We know that arg is our GlobalRefProxy instance pointing to the * SSLFDProxy class instance. This lets us ignore the PRFileDesc * parameter because we already have a reference to it via arg. * * All we need to do then is set SSLFDProxy@fd_ref's needBadCertValidation * to true. */ JNIEnv *env = NULL; jobject sslfd_proxy = (jobject) arg; jclass sslfdProxyClass; jfieldID needBadCertValidationField; jfieldID badCertErrorField; int cert_error = PR_GetError(); if (arg == NULL || fd == NULL || JSS_javaVM == NULL) { return SECFailure; } if ((*JSS_javaVM)->AttachCurrentThread(JSS_javaVM, (void**)&env, NULL) != JNI_OK || env == NULL) { return SECFailure; } sslfdProxyClass = (*env)->GetObjectClass(env, sslfd_proxy); if (sslfdProxyClass == NULL) { return SECFailure; } needBadCertValidationField = (*env)->GetFieldID(env, sslfdProxyClass, "needBadCertValidation", "Z"); if (needBadCertValidationField == NULL) { return SECFailure; } badCertErrorField = (*env)->GetFieldID(env, sslfdProxyClass, "badCertError", "I"); if (badCertErrorField == NULL) { return SECFailure; } (*env)->SetBooleanField(env, sslfd_proxy, needBadCertValidationField, JNI_TRUE); (*env)->SetIntField(env, sslfd_proxy, needBadCertValidationField, cert_error); return SECWouldBlock; } SECStatus JSSL_SSLFDSyncBadCertCallback(void *arg, PRFileDesc *fd) { /* We know that arg is our GlobalRefProxy instance pointing to the * SSLFDProxy class instance. This lets us ignore the PRFileDesc * parameter because we already have a reference to it via arg. * * All we need to do then is call SSLFDProxy@fd_ref's * invokeBadCertHandler() method. */ JNIEnv *env = NULL; jobject sslfd_proxy = (jobject) arg; jclass sslfdProxyClass; jmethodID badCertHandlerMethod; PRErrorCode ret; int cert_error = PR_GetError(); if (arg == NULL || fd == NULL || JSS_javaVM == NULL) { PR_SetError(SEC_ERROR_INVALID_ARGS, 0); return SECFailure; } if ((*JSS_javaVM)->AttachCurrentThread(JSS_javaVM, (void**)&env, NULL) != JNI_OK || env == NULL) { PR_SetError(PR_UNKNOWN_ERROR, 0); return SECFailure; } sslfdProxyClass = (*env)->GetObjectClass(env, sslfd_proxy); if (sslfdProxyClass == NULL) { PR_SetError(PR_UNKNOWN_ERROR, 0); return SECFailure; } badCertHandlerMethod = (*env)->GetMethodID(env, sslfdProxyClass, "invokeBadCertHandler", "(I)I"); if (badCertHandlerMethod == NULL) { PR_SetError(PR_UNKNOWN_ERROR, 0); return SECFailure; } ret = (*env)->CallIntMethod(env, sslfd_proxy, badCertHandlerMethod, cert_error); if ((*env)->ExceptionOccurred(env) != NULL) { ret = PR_UNKNOWN_ERROR; } PR_SetError(ret, 0); if (ret == 0) { return SECSuccess; } return SECFailure; } jss-5.0.0/src/main/java/org/mozilla/jss/nss/SSLFDProxy.h000066400000000000000000000026041412550063600227010ustar00rootroot00000000000000#include #include #include #pragma once PRStatus JSS_NSS_getSSLClientCert(JNIEnv *env, jobject sslfd_proxy, CERTCertificate **cert); PRStatus JSS_NSS_getSSLAlertSentList(JNIEnv *env, jobject sslfd_proxy, jobject *list); PRStatus JSS_NSS_getSSLAlertReceivedList(JNIEnv *env, jobject sslfd_proxy, jobject *list); PRStatus JSS_NSS_addSSLAlert(JNIEnv *env, jobject sslfd_proxy, jobject list, const SSLAlert *alert); PRStatus JSS_NSS_getGlobalRef(JNIEnv *env, jobject sslfd_proxy, jobject *global_ref); void JSSL_SSLFDAlertReceivedCallback(const PRFileDesc *fd, void *arg, const SSLAlert *alert); void JSSL_SSLFDAlertSentCallback(const PRFileDesc *fd, void *arg, const SSLAlert *alert); SECStatus JSSL_SSLFDCertSelectionCallback(void *arg, PRFileDesc *fd, CERTDistNames *caNames, CERTCertificate **pRetCert, SECKEYPrivateKey **pRetKey); void JSSL_SSLFDHandshakeComplete(PRFileDesc *fd, void *client_data); SECStatus JSSL_SSLFDAsyncCertAuthCallback(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer); SECStatus JSSL_SSLFDSyncCertAuthCallback(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer); SECStatus JSSL_SSLFDAsyncBadCertCallback(void *arg, PRFileDesc *fd); SECStatus JSSL_SSLFDSyncBadCertCallback(void *arg, PRFileDesc *fd); jss-5.0.0/src/main/java/org/mozilla/jss/nss/SSLFDProxy.java000066400000000000000000000033351412550063600233750ustar00rootroot00000000000000package org.mozilla.jss.nss; import java.lang.IllegalArgumentException; import java.util.ArrayList; import org.mozilla.jss.crypto.X509Certificate; import org.mozilla.jss.pkcs11.PK11Cert; import org.mozilla.jss.ssl.SSLAlertEvent; import org.mozilla.jss.util.GlobalRefProxy; public class SSLFDProxy extends PRFDProxy { public PK11Cert clientCert; public GlobalRefProxy globalRef; public ArrayList inboundAlerts; public int inboundOffset; public ArrayList outboundAlerts; public int outboundOffset; public boolean needCertValidation; public boolean needBadCertValidation; public int badCertError; public boolean handshakeComplete; public CertAuthHandler certAuthHandler; public BadCertHandler badCertHandler; public SSLFDProxy(byte[] pointer) { super(pointer); globalRef = new GlobalRefProxy(this); } public void SetClientCert(X509Certificate cert) throws IllegalArgumentException { if (!(cert instanceof PK11Cert)) { throw new IllegalArgumentException("Unable to cast given certificate to PK11Cert: " + cert.getClass().getName()); } clientCert = (PK11Cert)cert; } @Override protected synchronized void releaseNativeResources() throws Exception { synchronized (globalRef) { if (globalRef != null) { try { globalRef.close(); } finally { globalRef = null; } } } } public int invokeCertAuthHandler() { return certAuthHandler.check(this); } public int invokeBadCertHandler(int error) { return badCertHandler.check(this, error); } } jss-5.0.0/src/main/java/org/mozilla/jss/nss/SSLPreliminaryChannelInfo.java000066400000000000000000000345731412550063600264520ustar00rootroot00000000000000package org.mozilla.jss.nss; import java.lang.StringBuilder; import org.mozilla.jss.crypto.ObjectNotFoundException; import org.mozilla.jss.ssl.*; /** * Class representing the SSLPreliminaryChannelInfo struct from NSS's sslt.h. * * This class is a data class; it contains getters and no setters. It usually * should be constructed via a call to * org.mozilla.jss.nss.SSL.GetPreliminaryChannelInfo(SSLFDProxy inst) rather * than directly constructing an instance. * * This class works regardless of handshake status; in particular, it will * succeed when called early in the handshake. If a given set of fields are * known, support will be indicated via the haveFIELD functions. If the value * of this field isn't yet known, the function will return false. * * Field and getter names match that in the NSS equivalent struct. No fields * have been omitted. */ public class SSLPreliminaryChannelInfo { /** * Internal integer representing the fields with available data. */ private long valuesSet; /** * Which protocol version is used by this SSL socket. */ private SSLVersion protocolVersion; /** * Which cipher suite is used by this SSL socket. */ private SSLCipher cipherSuite; /** * Whether or not early data can be sent. * * This field was added in NSS 3.29. * * NSS gives the following description about this field: * * |canSendEarlyData| is true when a 0-RTT is enabled. This can only be * true after sending the ClientHello and before the handshake completes. */ private boolean canSendEarlyData; /** * The maximum amount of early data that can be sent. * * This field was added in NSS 3.31. * * NSS gives the following description of this field: * * The number of early data octets that a client is permitted to send on * this connection. The value will be zero if the connection was not * resumed or early data is not permitted. For a client, this value only * has meaning if |canSendEarlyData| is true. For a server, this indicates * the value that was advertised in the session ticket that was used to * resume this session. */ private long maxEarlyDataSize; /** * This field controls whether or not we have the zeroRttCipherSuite * field. * * When this field is true, zeroRttCipherSuite could be set with a value. * Otherwise, its value should be ignored. Check the corresponding field * function, haveZeroRttCipherSuite(), to see whether the handshake has * progressed far enough for this field to have a value. * * Note that the corresponding field is present when the version NSS used * to compile JSS and the runtime version of NSS match, and both have this * field. */ private boolean haveNSS343; /** * Which cipher suite is in use for 0RTT TLS 1.3 connections. * * This field was added in NSS 3.43. * * NSS gives the following description of this field: * * This reports the cipher suite used for 0-RTT if it sent or accepted. For * a client, this is set earlier than |cipherSuite|, and will match that * value if 0-RTT is accepted by the server. The server only sets this * after accepting 0-RTT, so this will contain the same value. */ private SSLCipher zeroRttCipherSuite; /** * This field controls whether or not we have the following three fields: * * - peerDelegCred, * - authKeyBits, and * - signatureScheme. * * When this field is true, these fields could be set with a value. * Otherwise, their values should be ignored. Check the corresponding * field function, havePeerAuth(), to see whether the handshake has * progressed far enough for this field to have a value. * * Note that the corresponding fields are present when the version NSS used * to compile JSS and the runtime version of NSS match, and both have these * fields. */ private boolean haveNSS348; /** * Whether or not the peer has offered a delegated field. * * This field was added in NSS 3.48. * * NSS gives the following description of these three fields: * * These fields contain information about the key that will be used in * the CertificateVerify message. If Delegated Credentials are being used, * this is the DC-contained SPKI, else the EE-cert SPKI. These fields are * valid only after the Certificate message is handled. This can be determined * by checking the valuesSet field against |ssl_preinfo_peer_auth|. */ private boolean peerDelegCred; /** * How many bits are in the authentication key. * * This field was added in NSS 3.48. * * See also: peerDelegCred and SSLChannelInfo's authKeyBits field. */ private int authKeyBits; /** * Signature scheme used. * * This field was added in NSS 3.48. * * See also: peerDelegCred and SSLChannelInfo's signatureScheme field. */ private SSLSignatureScheme signatureScheme; /** * Constructor used by SSL.GetPreliminaryChannelInfo(...). * * This translates between ints and enum constants. */ public SSLPreliminaryChannelInfo(long valuesSet, int protocolVersion, int cipherSuite, boolean canSendEarlyData, long maxEarlyDataSize, boolean haveNSS343, int zeroRttCipherSuite, boolean haveNSS348, boolean peerDelegCred, int authKeyBits, int signatureScheme) { this.valuesSet = valuesSet; if (haveProtocolVersion()) { try { this.protocolVersion = SSLVersion.valueOf(protocolVersion); } catch (IllegalArgumentException iae) { this.protocolVersion = null; } } if (haveCipherSuite()) { this.cipherSuite = SSLCipher.valueOf(cipherSuite); } this.canSendEarlyData = canSendEarlyData; this.maxEarlyDataSize = maxEarlyDataSize; this.haveNSS343 = haveNSS343; if (haveZeroRttCipherSuite()) { this.zeroRttCipherSuite = SSLCipher.valueOf(zeroRttCipherSuite); } this.haveNSS348 = haveNSS348; if (havePeerAuth()) { this.peerDelegCred = peerDelegCred; this.authKeyBits = authKeyBits; this.signatureScheme = SSLSignatureScheme.valueOf(signatureScheme); } } /** * Helper to check the valueSet bitmask for availability of the specified * field. */ private boolean haveField(long mask) { return (valuesSet & mask) == mask; } /** * Check this to see whether the value of protocolVersion can be used. * * Returns true if the handshake has progressed far enough for the value * of the field to be determined. */ public boolean haveProtocolVersion() { long ssl_preinfo_version = 1 << 0; return haveField(ssl_preinfo_version); } /** * Check this to see whether the value of cipherSuite can be used. * * Returns true if the handshake has progressed far enough for the value * of the field to be determined. */ public boolean haveCipherSuite() { long ssl_preinfo_cipher_suite = 1 << 1; return haveField(ssl_preinfo_cipher_suite); } /** * Check this to see whether the value of zeroRttCipherSuite can be used. * * Returns true if the handshake has progressed far enough for the value * of the field to be determined. */ public boolean haveZeroRttCipherSuite() { long ssl_preinfo_0rtt_cipher_suite = 1 << 2; return haveField(ssl_preinfo_0rtt_cipher_suite) && haveNSS343; } /** * Check this to see whether the value of the peerDelegCred, authKeyBits, * and signatureScheme fields can be used. * * Returns true if the handshake has progressed far enough for the value * of the fields to be determined. */ public boolean havePeerAuth() { long ssl_preinfo_peer_auth = 1 << 3; return haveField(ssl_preinfo_peer_auth) && haveNSS348; } /** * Gets the value of protocolVersion; throws an exception when the value * isn't yet available. * * See also: protocolVersion. */ public SSLVersion getProtocolVersion() throws ObjectNotFoundException { if (!haveProtocolVersion()) { String msg = "The protocolVersion field isn't yet available at "; msg += "this point in the TLS handshake; wait for "; msg += "haveProtocolVersion(...) to return true before calling."; throw new ObjectNotFoundException(msg); } return protocolVersion; } /** * Gets the value of cipherSuite; throws an exception when the value * isn't yet available. * * See also: cipherSuite. */ public SSLCipher getCipherSuite() throws ObjectNotFoundException { if (!haveCipherSuite()) { String msg = "The cipherSuite field isn't yet available at this "; msg += "point in the TLS handshake; wait for "; msg += "haveCipherSuite(...) to return true before calling."; throw new ObjectNotFoundException(msg); } return cipherSuite; } /** * Gets the value of zeroRttCipherSuite; throws an exception when the * value isn't yet available. * * See also: zeroRttCipherSuite. */ public SSLCipher getZeroRttCipherSuite() throws ObjectNotFoundException { if (!haveNSS343) { String msg = "The version of NSS used to compile JSS doesn't "; msg += "support this field in SSLPreliminaryChannelInfo. Either "; msg += "backport this feature or upgrade to at least NSS v3.43. "; msg += "Check the value of "; msg += "HAVE_NSS_PRELIMINARY_CHANNEL_INFO_ZERO_RTT_CIPHER_SUITE "; msg += "when building JSS."; throw new ObjectNotFoundException(msg); } if (!haveZeroRttCipherSuite()) { String msg = "The zeroRttCipherSuite field isn't yet available "; msg += "at this point in the TLS handshake; wait for "; msg += "haveZeroRttCipherSuite(...) to return true before "; msg += "calling."; throw new ObjectNotFoundException(msg); } return zeroRttCipherSuite; } /** * Gets the value of peerDelegCred; throws an exception when the value * isn't yet available. * * See also: peerDelegCred. */ public boolean getPeerDelegCred() throws ObjectNotFoundException { if (!haveNSS348) { String msg = "The version of NSS used to compile JSS doesn't "; msg += "support this field in SSLPreliminaryChannelInfo. Either "; msg += "backport this feature or upgrade to at least NSS v3.48. "; msg += "Check the value of "; msg += "HAVE_NSS_PRELIMINARY_CHANNEL_INFO_PEER_DELEG_CRED "; msg += "when building JSS."; throw new ObjectNotFoundException(msg); } if (!havePeerAuth()) { String msg = "The peerDelegCred field isn't yet available at "; msg += "this point in the TLS handshake; wait for "; msg += "havePeerAuth(...) to return true before calling."; throw new ObjectNotFoundException(msg); } return peerDelegCred; } /** * Gets the value of authKeyBits; throws an exception when the value isn't * yet available. * * See also: authKeyBits. */ public int getAuthKeyBits() throws ObjectNotFoundException { if (!haveNSS348) { String msg = "The version of NSS used to compile JSS doesn't "; msg += "support this field in SSLPreliminaryChannelInfo. Either "; msg += "backport this feature or upgrade to at least NSS v3.48. "; msg += "Check the value of "; msg += "HAVE_NSS_PRELIMINARY_CHANNEL_INFO_PEER_DELEG_CRED "; msg += "when building JSS."; throw new ObjectNotFoundException(msg); } if (!havePeerAuth()) { String msg = "The authKeyBits field isn't yet available at "; msg += "this point in the TLS handshake; wait for "; msg += "havePeerAuth(...) to return true before calling."; throw new ObjectNotFoundException(msg); } return authKeyBits; } /** * Gets the value of signatureScheme; throws an exception when the value * isn't yet available. * * See also: signatureScheme. */ public SSLSignatureScheme getSignatureScheme() throws ObjectNotFoundException { if (!haveNSS348) { String msg = "The version of NSS used to compile JSS doesn't "; msg += "support this field in SSLPreliminaryChannelInfo. Either "; msg += "backport this feature or upgrade to at least NSS v3.48. "; msg += "Check the value of "; msg += "HAVE_NSS_PRELIMINARY_CHANNEL_INFO_PEER_DELEG_CRED "; msg += "when building JSS."; throw new ObjectNotFoundException(msg); } if (!havePeerAuth()) { String msg = "The signatureScheme field isn't yet available at "; msg += "this point in the TLS handshake; wait for "; msg += "havePeerAuth(...) to return true before calling."; throw new ObjectNotFoundException(msg); } return signatureScheme; } /** * Returns a string representation of the data in this data structure. */ @Override public String toString() { StringBuilder result = new StringBuilder("SSLPreliminaryChannelInfo:"); if (haveProtocolVersion()) { result.append("\n- protocolVersion: " + protocolVersion); } if (haveCipherSuite()) { result.append("\n- cipherSuite: " + cipherSuite); } result.append("\n- canSendEarlyData: " + canSendEarlyData); result.append("\n- maxEarlyDataSize: " + maxEarlyDataSize); if (haveZeroRttCipherSuite()) { result.append("\n- zeroRttCipherSuite: " + zeroRttCipherSuite); } if (havePeerAuth()) { result.append("\n- peerDelegCred: " + peerDelegCred); result.append("\n- authKeyBits: " + authKeyBits); result.append("\n- signatureScheme: " + signatureScheme); } return result.toString(); } } jss-5.0.0/src/main/java/org/mozilla/jss/nss/SecurityStatusResult.java000066400000000000000000000035651412550063600256770ustar00rootroot00000000000000package org.mozilla.jss.nss; import java.lang.StringBuilder; /** * The fields in a SecurityStatusResult indicate whether a given SSL-enabled * PRFileDesc has completed its handshake and the resulting handshake-specific * information. * * These object is returned by org.mozilla.jss.nss.SSL.SecurityStatus(fd). */ public class SecurityStatusResult { /* Whether or not the handshake has completed successfully. */ public int on; /* The current ciphersuite used. */ public byte[] cipher; /* Size of the negotiated peer key. */ public int keySize; /* Size of the session secret key. */ public int secretKeySize; /* Issuer of the peer's certificate. */ public byte[] issuer; /* Subject of the peer's certificate. */ public byte[] subject; public SecurityStatusResult(int _on, byte[] _cipher, int _keySize, int _secretKeySize, byte[] _issuer, byte[] _subject) { this.on = _on; this.cipher = _cipher; this.keySize = _keySize; this.secretKeySize = _secretKeySize; this.issuer = _issuer; this.subject = _subject; } @Override public String toString() { StringBuilder result = new StringBuilder("SecurityStatusResult:"); result.append("\n- on: " + on); if (cipher != null && cipher.length > 0) { result.append("\n- cipher: "); result.append(new String(cipher)); } result.append("\n- keySize: " + keySize); result.append("\n- secretKeySize: " + secretKeySize); if (issuer != null && issuer.length > 0) { result.append("\n- issuer: "); result.append(new String(issuer)); } if (subject != null && subject.length > 0) { result.append("\n- subject: "); result.append(new String(subject)); } return result.toString(); } } jss-5.0.0/src/main/java/org/mozilla/jss/package.html000066400000000000000000000004541412550063600222720ustar00rootroot00000000000000 Configuration and top-level operations of the JSS system. jss-5.0.0/src/main/java/org/mozilla/jss/pkcs10/000077500000000000000000000000001412550063600211075ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/pkcs10/CertificationRequest.java000066400000000000000000000272411412550063600261140ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs10; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.InvalidKeyException; import java.security.KeyPair; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.SignatureException; import java.security.cert.CertificateException; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BIT_STRING; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.InvalidKeyFormatException; import org.mozilla.jss.crypto.KeyPairAlgorithm; import org.mozilla.jss.crypto.KeyPairGenerator; import org.mozilla.jss.crypto.PrivateKey; import org.mozilla.jss.crypto.Signature; import org.mozilla.jss.crypto.SignatureAlgorithm; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; import org.mozilla.jss.pkix.primitive.Name; /** * A pkcs10 signed CertificationRequest. */ public class CertificationRequest implements ASN1Value { private CertificationRequestInfo info; private byte[] infoEncoding; private byte[] signature; private AlgorithmIdentifier algId; SEQUENCE sequence; CertificationRequest(CertificationRequestInfo info, //byte[] infoEncoding, AlgorithmIdentifier algId, byte[] signature) throws IOException { this.info = info; //this.infoEncoding = infoEncoding; this.algId = algId; this.signature = signature; // bundle everything into a SEQUENCE sequence = new SEQUENCE(); sequence.addElement( info ); sequence.addElement( algId ); sequence.addElement( new BIT_STRING( signature, 0 ) ); } /** * Creates and signs an X.509 CertificationRequest. * @param info A CertificationRequestInfo (TBSCertificationRequest), * which specifies * the actual information of the CertificationRequest. * @param privKey The private key with which to sign the certificate. * @param signingAlg The algorithm to use to sign the CertificationRequest. * It must match the algorithm specified in the CertificationRequestInfo. * @exception IOException If an error occurred while encoding the * CertificationRequest. * @exception NotInitializedException Because this * operation involves cryptography (signing), CryptoManager must * be initialized before calling it. * @exception TokenException If an error occurs on a PKCS #11 token. * @exception NoSuchAlgorithmException If the OID for the signing algorithm * cannot be located. * @exception CertificateException If the signing algorithm specified * as a parameter does not match the one in the CertificationRequest info. * @exception InvalidKeyException If the key does not match the signing * algorithm. * @exception SignatureException If an error occurs while signing the * CertificationRequest. */ public CertificationRequest(CertificationRequestInfo info, java.security.PrivateKey privKey, SignatureAlgorithm signingAlg) throws IOException, NotInitializedException, TokenException, NoSuchAlgorithmException, CertificateException, InvalidKeyException, SignatureException { // make sure key is a Ninja private key if( !(privKey instanceof PrivateKey) ) { throw new InvalidKeyException("Private Key is does not belong to"+ " this provider"); } PrivateKey priv = (PrivateKey)privKey; // create algId if(signingAlg.getSigningAlg() == SignatureAlgorithm.RSASignature) { algId = new AlgorithmIdentifier( signingAlg.toOID(), null ); } else { algId = new AlgorithmIdentifier( signingAlg.toOID() ); } // encode the cert info this.info = info; infoEncoding = ASN1Util.encode(info); // sign the info encoding CryptoManager cm = CryptoManager.getInstance(); CryptoToken token = priv.getOwningToken(); Signature sig = token.getSignatureContext(signingAlg); sig.initSign(priv); sig.update(infoEncoding); signature = sig.sign(); // bundle everything into a SEQUENCE sequence = new SEQUENCE(); sequence.addElement( info ); sequence.addElement( algId ); sequence.addElement( new BIT_STRING( signature, 0 ) ); } /** * Verifies the signature on this CertificationRequest. Does not indicate * that the CertificationRequest is valid at any specific time. */ public void verify() throws InvalidKeyException, NotInitializedException, NoSuchAlgorithmException, CertificateException, TokenException, SignatureException, InvalidKeyFormatException { verify( info.getSubjectPublicKeyInfo().toPublicKey() ); } /** * Verifies the signature on this CertificationRequest, using the given public key. * Does not indicate the CertificationRequest is valid at any specific time. */ public void verify(PublicKey key) throws InvalidKeyException, NotInitializedException, NoSuchAlgorithmException, CertificateException, TokenException, SignatureException { CryptoManager cm = CryptoManager.getInstance(); verify(key, cm.getInternalCryptoToken()); } /** * Verifies the signature on this CertificationRequest, using the given public * key and CryptoToken. Does not indicate the CertificationRequest is valid at * any specific time. */ public void verify(PublicKey key, CryptoToken token) throws NoSuchAlgorithmException, CertificateException, TokenException, SignatureException, InvalidKeyException { Signature sig = token.getSignatureContext( SignatureAlgorithm.fromOID( algId.getOID() ) ); sig.initVerify(key); sig.update(infoEncoding); if( ! sig.verify(signature) ) { throw new CertificateException("Signature is invalid"); } } /** * Returns the information (TBSCertificationRequest) contained in this CertificationRequest. */ public CertificationRequestInfo getInfo() { return info; } private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( CertificationRequestInfo.getTemplate() ); //seqt.addElement( new ANY.Template() ); seqt.addElement( AlgorithmIdentifier.getTemplate() ); seqt.addElement( BIT_STRING.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); //ANY infoAny = (ANY)seq.elementAt(0); //byte[] infoEncoding = infoAny.getEncoded(); /*CertificationRequestInfo info = (CertificationRequestInfo) infoAny.decodeWith( CertificationRequestInfo.getTemplate() ); */ CertificationRequestInfo info = (CertificationRequestInfo) seq.elementAt(0); // although signature is a bit string, all algorithms we use // will produce an octet string. BIT_STRING bs = (BIT_STRING) seq.elementAt(2); if( bs.getPadCount() != 0 ) { throw new InvalidBERException("signature does not fall into"+ " an integral number of bytes"); } byte[] signature = bs.getBits(); return new CertificationRequest( info, //infoEncoding, (AlgorithmIdentifier) seq.elementAt(1), signature ); } } public static void main(String argv[]) { try { if(argv.length > 2 || argv.length < 1) { System.out.println("Usage: CertificationRequest []"); System.exit(0); } CryptoManager.initialize( argv[0] ); CryptoManager cm = CryptoManager.getInstance(); CertificationRequest cert; // read in a cert FileInputStream fis = new FileInputStream(argv[1]); try (BufferedInputStream bis = new BufferedInputStream(fis)) { cert = (CertificationRequest) CertificationRequest.getTemplate().decode(bis); } CertificationRequestInfo info = cert.getInfo(); info.print(System.out); //X509CertificationRequest hardcore = cm.findCertByNickname("Hardcore"); //PublicKey key = hardcore.getPublicKey(); cert.verify(); System.out.println("verified"); FileOutputStream fos = new FileOutputStream("certinfo.der"); info.encode(fos); fos.close(); // make a new public key CryptoToken token = cm.getInternalKeyStorageToken(); KeyPairGenerator kpg = token.getKeyPairGenerator(KeyPairAlgorithm.RSA); kpg.initialize(512); System.out.println("Generating a new key pair..."); KeyPair kp = kpg.genKeyPair(); System.out.println("Generated key pair"); // set the CertificationRequest's public key info.setSubjectPublicKeyInfo(kp.getPublic()); // make new Name Name name = new Name(); name.addCommonName("asldkj"); name.addCountryName("US"); name.addOrganizationName("Some Corp"); name.addOrganizationalUnitName("Some Org Unit"); name.addLocalityName("Silicon Valley"); name.addStateOrProvinceName("California"); info.setSubject(name); System.out.println("About to create a new cert request..."); // create a new cert requestfrom this certReqinfo CertificationRequest genCert = new CertificationRequest(info, kp.getPrivate(), SignatureAlgorithm.RSASignatureWithMD5Digest); System.out.println("Created new cert request"); genCert.verify(); System.out.println("Cert verifies!"); fos = new FileOutputStream("gencert.der"); genCert.encode(fos); fos.close(); } catch( Exception e ) { e.printStackTrace(); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs10/CertificationRequestInfo.java000066400000000000000000000121501412550063600267210ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs10; import org.mozilla.jss.asn1.*; import org.mozilla.jss.pkix.primitive.*; import java.security.PublicKey; import java.io.InputStream; import java.io.PrintStream; import java.io.OutputStream; import java.io.IOException; /** * A TBSCertificationRequest (to-be-signed CertificationRequest), * the actual information in * a CertificationRequest apart from the signature. */ public class CertificationRequestInfo implements ASN1Value { private INTEGER version = new INTEGER(0); private Name subject; private SubjectPublicKeyInfo subjectPublicKeyInfo; private SET attributes; /** * Creates a CertificationRequestInfo with the required fields. */ public CertificationRequestInfo(INTEGER version, Name subject, SubjectPublicKeyInfo subjectPublicKeyInfo, SET attributes) { setVersion(version); setSubject(subject); setSubjectPublicKeyInfo(subjectPublicKeyInfo); setAttributes(attributes); } public void setVersion(INTEGER version) { verifyNotNull(version); this.version = version; } public INTEGER getVersion() { return version; } public void setSubject(Name subject) { verifyNotNull(subject); this.subject = subject; } public Name getSubject() { return subject; } public void setSubjectPublicKeyInfo( SubjectPublicKeyInfo subjectPublicKeyInfo) { verifyNotNull(subjectPublicKeyInfo); this.subjectPublicKeyInfo = subjectPublicKeyInfo; } /** * Extracts the SubjectPublicKeyInfo from the given public key and * stores it in the CertificationRequestInfo. * * @exception InvalidBERException If an error occurs decoding the * the information extracted from the public key. */ public void setSubjectPublicKeyInfo( PublicKey pubk ) throws InvalidBERException, IOException { verifyNotNull(pubk); setSubjectPublicKeyInfo( new SubjectPublicKeyInfo(pubk) ); } public SubjectPublicKeyInfo getSubjectPublicKeyInfo() { return subjectPublicKeyInfo; } public void setAttributes(SET attributes) { //verifyNotNull(attributes); this.attributes = attributes; } public SET getAttributes() { return attributes; } private void verifyNotNull(Object obj) { if( obj == null ) { throw new NullPointerException(); } } static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); seq.addElement(version ); seq.addElement(subject); seq.addElement(subjectPublicKeyInfo); seq.addElement(new Tag(0), attributes); seq.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } public void print(PrintStream ps) throws IOException, InvalidBERException { ps.println("CertificationRequestInfo:"); ps.println("Version: "+version); ps.println("Subject: "+subject.getRFC1485()); } /** * Template class for decoding a CertificationRequestInfo. */ public static class Template implements ASN1Template { SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement(INTEGER.getTemplate()); //version seqt.addElement(Name.getTemplate()); //subject seqt.addElement(SubjectPublicKeyInfo.getTemplate()); seqt.addElement(Tag.get(0), new SET.OF_Template(Attribute.getTemplate())); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { try { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); CertificationRequestInfo cinfo = new CertificationRequestInfo( (INTEGER) seq.elementAt(0), // version (Name) seq.elementAt(1), // subject (SubjectPublicKeyInfo) seq.elementAt(2), (SET) seq.elementAt(3) ); return cinfo; } catch( Exception e ) { throw new InvalidBERException(e.getMessage()); } } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs10/package.html000066400000000000000000000004271412550063600233730ustar00rootroot00000000000000 Encoding and decoding pkcs10 request jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/000077500000000000000000000000001412550063600211105ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/CipherContextProxy.java000066400000000000000000000010771412550063600256010ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import org.mozilla.jss.util.NativeProxy; final class CipherContextProxy extends NativeProxy { public CipherContextProxy(byte[] pointer) { super(pointer); } @Override protected native void releaseNativeResources(); @Override protected void finalize() throws Throwable { super.finalize(); } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/KeyProxy.java000066400000000000000000000007331412550063600235500ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; abstract class KeyProxy extends org.mozilla.jss.util.NativeProxy { protected KeyProxy(byte[] pointer) { super(pointer); } @Override protected void finalize() throws Throwable { super.finalize(); } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/KeyType.java000066400000000000000000000235711412550063600233550ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import java.security.NoSuchAlgorithmException; import java.util.Hashtable; import org.mozilla.jss.crypto.Algorithm; import org.mozilla.jss.crypto.EncryptionAlgorithm; import org.mozilla.jss.crypto.CMACAlgorithm; import org.mozilla.jss.crypto.HMACAlgorithm; import org.mozilla.jss.crypto.KeyWrapAlgorithm; import org.mozilla.jss.crypto.SignatureAlgorithm; /** * PKCS #11 Key Types * These are the possible types for keys in the * wrapper library. * Key types are implemented as flyweights. * * Although the KeyType class is public, it should * be considered private. We made the KeyType class * public so that we can force it to load during * CryptoManager.initialize(), before we install JSS * as a provider. **/ public final class KeyType { protected KeyType() {} protected KeyType(Algorithm[] algs, String name) { int i; assert(algs!=null); algorithms = algs.clone(); // Register this key as the key type for each of its algorithms for(i=0; i < algorithms.length; i++) { assert(! algHash.containsKey(algorithms[i]) ); algHash.put(algorithms[i], this); } this.name = name; } /** * Returns an array of algorithms supported by this key type. */ public Algorithm[] supportedAlgorithms() { return algorithms; } /** * Returns the KeyType corresponding to the given Algorithm. If there * is no KeyType registered for this algorithm, a NoSuchAlgorithmException * is thrown. */ static public KeyType getKeyTypeFromAlgorithm(Algorithm alg) throws NoSuchAlgorithmException { assert(alg!=null); Object obj = algHash.get(alg); if(obj == null) { throw new NoSuchAlgorithmException(); } assert( obj instanceof KeyType ); return (KeyType) obj; } @Override public String toString() { return name; } ////////////////////////////////////////////////////////////// // Instance Data ////////////////////////////////////////////////////////////// // An array of algorithms supported by this key type protected Algorithm[] algorithms; protected String name; ////////////////////////////////////////////////////////////// // Class Data ////////////////////////////////////////////////////////////// // A hash table associating a key type with each algorithm static protected Hashtable algHash; static { algHash = new Hashtable<>(); } ////////////////////////////////////////////////////////////// // Key Types ////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// static public final KeyType NULL = new KeyType(new Algorithm[0], "NULL"); ////////////////////////////////////////////////////////////// static public final KeyType RSA = new KeyType (new Algorithm[] { SignatureAlgorithm.RSASignature, SignatureAlgorithm.RSASignatureWithMD2Digest, SignatureAlgorithm.RSASignatureWithMD5Digest, SignatureAlgorithm.RSASignatureWithSHA1Digest, SignatureAlgorithm.RSASignatureWithSHA256Digest, SignatureAlgorithm.RSASignatureWithSHA384Digest, SignatureAlgorithm.RSASignatureWithSHA512Digest, SignatureAlgorithm.RSAPSSSignature, SignatureAlgorithm.RSAPSSSignatureWithSHA256Digest, SignatureAlgorithm.RSAPSSSignatureWithSHA384Digest, SignatureAlgorithm.RSAPSSSignatureWithSHA512Digest, KeyWrapAlgorithm.RSA, KeyWrapAlgorithm.RSA_OAEP, }, "RSA" ); ////////////////////////////////////////////////////////////// static public final KeyType DSA = new KeyType(new Algorithm[] { SignatureAlgorithm.DSASignature, SignatureAlgorithm.DSASignatureWithSHA1Digest }, "DSA" ); ////////////////////////////////////////////////////////////// static public final KeyType EC = new KeyType(new Algorithm[] { SignatureAlgorithm.ECSignature, SignatureAlgorithm.ECSignatureWithSHA1Digest, SignatureAlgorithm.ECSignatureWithSHA256Digest, SignatureAlgorithm.ECSignatureWithSHA384Digest, SignatureAlgorithm.ECSignatureWithSHA512Digest }, "EC" ); ////////////////////////////////////////////////////////////// /** * @deprecated As of NSS 3.11, FORTEZZA is no longer supported. * This is just a placeholder for backward compatibility. */ @Deprecated static public final KeyType FORTEZZA = new KeyType(new Algorithm[0], "FORTEZZA"); ////////////////////////////////////////////////////////////// static public final KeyType DH = new KeyType(new Algorithm[0], "DH"); ////////////////////////////////////////////////////////////// static public final KeyType KEA = new KeyType(new Algorithm[0], "KEA"); ////////////////////////////////////////////////////////////// static public final KeyType DES = new KeyType(new Algorithm[] { KeyWrapAlgorithm.DES_ECB, KeyWrapAlgorithm.DES_CBC, KeyWrapAlgorithm.DES_CBC_PAD, EncryptionAlgorithm.DES_ECB, EncryptionAlgorithm.DES_CBC, EncryptionAlgorithm.DES_CBC_PAD }, "DES" ); ////////////////////////////////////////////////////////////// static public final KeyType DES3 = new KeyType(new Algorithm[] { KeyWrapAlgorithm.DES3_ECB, KeyWrapAlgorithm.DES3_CBC, KeyWrapAlgorithm.DES3_CBC_PAD, EncryptionAlgorithm.DES3_ECB, EncryptionAlgorithm.DES3_CBC, EncryptionAlgorithm.DES3_CBC_PAD }, "DESede" ); ////////////////////////////////////////////////////////////// static public final KeyType AES = new KeyType(new Algorithm[] { KeyWrapAlgorithm.AES_ECB, KeyWrapAlgorithm.AES_CBC, KeyWrapAlgorithm.AES_CBC_PAD, KeyWrapAlgorithm.AES_KEY_WRAP, KeyWrapAlgorithm.AES_KEY_WRAP_PAD, KeyWrapAlgorithm.AES_KEY_WRAP_PAD_KWP, EncryptionAlgorithm.AES_128_ECB, EncryptionAlgorithm.AES_128_CBC, EncryptionAlgorithm.AES_192_ECB, EncryptionAlgorithm.AES_192_CBC, EncryptionAlgorithm.AES_256_ECB, EncryptionAlgorithm.AES_256_CBC, EncryptionAlgorithm.AES_CBC_PAD, EncryptionAlgorithm.AES_128_CBC_PAD, EncryptionAlgorithm.AES_192_CBC_PAD, EncryptionAlgorithm.AES_256_CBC_PAD, CMACAlgorithm.AES }, "AES" ); ////////////////////////////////////////////////////////////// static public final KeyType RC4 = new KeyType(new Algorithm[] { EncryptionAlgorithm.RC4 }, "RC4" ); ////////////////////////////////////////////////////////////// static public final KeyType RC2 = new KeyType(new Algorithm[] { EncryptionAlgorithm.RC2_CBC, EncryptionAlgorithm.RC2_CBC_PAD }, "RC2" ); ////////////////////////////////////////////////////////////// static public final KeyType SHA1_HMAC = new KeyType(new Algorithm[] { HMACAlgorithm.SHA1 }, "SHA1_HMAC" ); static public final KeyType SHA256_HMAC = new KeyType(new Algorithm[] { HMACAlgorithm.SHA256 }, "SHA256_HMAC" ); static public final KeyType SHA384_HMAC = new KeyType(new Algorithm[] { HMACAlgorithm.SHA384 }, "SHA384_HMAC" ); static public final KeyType SHA512_HMAC = new KeyType(new Algorithm[] { HMACAlgorithm.SHA512 }, "SHA512_HMAC" ); static public final KeyType GENERIC_SECRET = new KeyType(new Algorithm[] { }, "GENERIC_SECRET"); } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/ModuleProxy.java000066400000000000000000000010421412550063600242370ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import org.mozilla.jss.util.*; final class ModuleProxy extends NativeProxy { ModuleProxy(byte[] pointer) { super(pointer); } @Override protected native void releaseNativeResources(); @Override protected void finalize() throws Throwable { super.finalize(); } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11Cert.c000066400000000000000000000507661412550063600225640ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "_jni/org_mozilla_jss_pkcs11_CertProxy.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pk11util.h" #include /* * Class: org_mozilla_jss_pkcs11_PK11Cert * Method: getEncoded * Signature: ()[B */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11Cert_getEncoded (JNIEnv *env, jobject this) { PRThread * VARIABLE_MAY_NOT_BE_USED pThread; CERTCertificate *cert; SECItem *derCert; jbyteArray derArray=NULL; pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); PR_ASSERT(pThread != NULL); PR_ASSERT(env!=NULL && this!=NULL); /* * extract the DER cert from the CERTCertificate* */ if( JSS_PK11_getCertPtr(env, this, &cert) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } PR_ASSERT(cert != NULL); derCert = &cert->derCert; /* the SECItem type does not have to be siDERCertBuffer */ if(derCert->data==NULL || derCert->len<1) { JSS_throw(env, CERTIFICATE_ENCODING_EXCEPTION); goto finish; } /* * Copy the DER data to a new Java byte array */ derArray = JSS_ToByteArray(env, derCert->data, derCert->len); if (derArray == NULL) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } finish: PR_DetachThread(); return derArray; } /* * Class: org_mozilla_jss_pkcs11_PK11Cert * Method: getVersion * Signature: ()I */ JNIEXPORT jint JNICALL Java_org_mozilla_jss_pkcs11_PK11Cert_getVersion (JNIEnv *env, jobject this) { PRThread * VARIABLE_MAY_NOT_BE_USED pThread; CERTCertificate *cert; long lVersion = 0; pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); PR_ASSERT(pThread != NULL); PR_ASSERT(env!=NULL && this!=NULL); /* * Get the version from the CERTCertificate * */ if( JSS_PK11_getCertPtr(env, this, &cert) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } PR_ASSERT(cert!=NULL); if(cert->version.data==NULL || cert->version.len<=0) { /* default value is 0 */ lVersion = 0; goto finish; } lVersion = DER_GetInteger(&cert->version); /* jint is 2s complement 32 bits. The max value is 0111...111. */ PR_ASSERT( (lVersion >= 0L) && (lVersion < (long)0x7fffffff) ); finish: PR_DetachThread(); return (jint) lVersion; } /****************************************************************** * * C e r t P r o x y . g e t P u b l i c K e y * * Extracts the SECKEYPublicKey from the CERTCertificate, wraps it * in a Java wrapper, and returns it. */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11Cert_getPublicKey (JNIEnv *env, jobject this) { CERTCertificate *cert; SECKEYPublicKey *pubk=NULL; PRThread * VARIABLE_MAY_NOT_BE_USED pThread; jobject pubKey=NULL; PR_ASSERT(env!=NULL && this!=NULL); pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); PR_ASSERT(pThread != NULL); if( JSS_PK11_getCertPtr(env, this, &cert) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } pubk = CERT_ExtractPublicKey(cert); if(pubk==NULL) { PR_ASSERT( PR_GetError() == SEC_ERROR_NO_MEMORY); JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } pubKey = JSS_PK11_wrapPubKey(env, &pubk); if(pubKey == NULL) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } finish: if(pubk!=NULL) { SECKEY_DestroyPublicKey(pubk); } PR_DetachThread(); return pubKey; } /****************************************************************** * * C e r t P r o x y . r e l e a s e N a t i v e R e s o u r c e s * * Calls CERT_DestroyCertificate on the underlying CERTCertificate. */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_CertProxy_releaseNativeResources (JNIEnv *env, jobject this) { CERTCertificate *cert = NULL; PRThread * VARIABLE_MAY_NOT_BE_USED pThread; PR_ASSERT(env!=NULL && this!=NULL); pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); PR_ASSERT(pThread != NULL); /* Get the CERTCertificate structure */ if(JSS_getPtrFromProxy(env, this, (void**)&cert) != PR_SUCCESS) { PR_ASSERT( PR_FALSE ); goto finish; } if (cert != NULL) { CERT_DestroyCertificate(cert); } finish: PR_DetachThread(); } /****************************************************************** * * J S S _ P K 1 1 _ g e t C e r t P t r * * Given a Certificate object, extracts the CERTCertificate* and * stores it at the given address. * * certObject: A JNI reference to a JSS Certificate object. * ptr: Address of a CERTCertificate* that will receive the pointer. * Returns: PR_SUCCESS for success, PR_FAILURE if an exception was thrown. */ PRStatus JSS_PK11_getCertPtr(JNIEnv *env, jobject certObject, CERTCertificate **ptr) { PR_ASSERT(env!=NULL && certObject!=NULL && ptr!=NULL); /* Get the pointer from the cert proxy */ return JSS_getPtrFromProxyOwner(env, certObject, CERT_PROXY_FIELD, CERT_PROXY_SIG, (void**)ptr); } /****************************************************************** * * J S S _ P K 1 1 _ g e t C e r t S l o t P t r * * Given a Certificate object, extracts the PK11SlotInfo* and * stores it at the given address. * * certObject: A JNI reference to a JSS Certificate object. * ptr: Address of a PK11SlotInfo* that will receive the pointer. * Returns: PR_SUCCESS for success, PR_FAILURE if an exception was thrown. */ PRStatus JSS_PK11_getCertSlotPtr(JNIEnv *env, jobject certObject, PK11SlotInfo **ptr) { PR_ASSERT(env!=NULL && certObject!=NULL && ptr!=NULL); /* Get the pointer from the token proxy */ return JSS_getPtrFromProxyOwner(env, certObject, PK11TOKEN_PROXY_FIELD, PK11TOKEN_PROXY_SIG, (void**)ptr); } /* * This is a shady way of deciding if the cert is a user cert. * Hopefully it will work. What we used to do was check for cert->slot. */ #define isUserCert(cert) \ ( ((cert)->trust->sslFlags & CERTDB_USER) || \ ((cert)->trust->emailFlags & CERTDB_USER) || \ ((cert)->trust->objectSigningFlags & CERTDB_USER) ) /**************************************************************** * * f i n d S l o t B y T o k e n N a m e A n d C e r t * * Find the slot containing the token with the given name * and cert. */ static PK11SlotInfo * findSlotByTokenNameAndCert(char *name, CERTCertificate *cert) { PK11SlotList *list; PK11SlotListElement *le; PK11SlotInfo *slot = NULL; list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_FALSE, NULL); if(list == NULL) { return NULL; } for(le = list->head; le; le = le->next) { if( (PORT_Strcmp(PK11_GetTokenName(le->slot),name) == 0) && (PK11_FindCertInSlot(le->slot,cert,NULL) != CK_INVALID_HANDLE)) { slot = PK11_ReferenceSlot(le->slot); break; } } PK11_FreeSlotList(list); if(slot == NULL) { PORT_SetError(SEC_ERROR_NO_TOKEN); } return slot; } /************************************************************************* * * J S S _ P K 1 1 _ f i n d C e r t A n d S l o t F r o m N i c k n a m e * * A variant of NSS's PK11_FindCertFromNickname function that also * returns a PK11SlotInfo* in *ppSlot. * * If nickname is of the format "token:nickname", the slot that * contains the specified token is returned. Otherwise the internal * key slot (which contains the permanent database token) is returned. */ CERTCertificate * JSS_PK11_findCertAndSlotFromNickname(const char *nickname, void *wincx, PK11SlotInfo **ppSlot) { CERTCertificate *cert; cert = PK11_FindCertFromNickname(nickname, wincx); if(cert == NULL) { return NULL; } if( PORT_Strchr(nickname, ':')) { char* tokenname = PORT_Strdup(nickname); char* colon = PORT_Strchr(tokenname, ':'); *colon = '\0'; *ppSlot = findSlotByTokenNameAndCert(tokenname, cert); PORT_Free(tokenname); if(*ppSlot == NULL) { /* The token containing the cert was just removed. */ CERT_DestroyCertificate(cert); return NULL; } } else { *ppSlot = PK11_GetInternalKeySlot(); } return cert; } /*************************************************************************** * * J S S _ P K 1 1 _ f i n d C e r t s A n d S l o t F r o m N i c k n a m e * * A variant of NSS's PK11_FindCertsFromNickname function that also * returns a PK11SlotInfo* in *ppSlot. * * If nickname is of the format "token:nickname", the slot that * contains the specified token is returned. Otherwise the internal * key slot (which contains the permanent database token) is returned. */ CERTCertList * JSS_PK11_findCertsAndSlotFromNickname(char *nickname, void *wincx, PK11SlotInfo **ppSlot) { CERTCertList *certList; certList = PK11_FindCertsFromNickname(nickname, wincx); if(certList == NULL) { return NULL; } if( PORT_Strchr(nickname, ':')) { char* tokenname = PORT_Strdup(nickname); char* colon = PORT_Strchr(tokenname, ':'); CERTCertListNode *head = CERT_LIST_HEAD(certList); *colon = '\0'; *ppSlot = findSlotByTokenNameAndCert(tokenname, head->cert); PORT_Free(tokenname); if(*ppSlot == NULL) { /* The token containing the certs was just removed. */ CERT_DestroyCertList(certList); return NULL; } } else { *ppSlot = PK11_GetInternalKeySlot(); } return certList; } /*********************************************************************** * * J S S _ P K 1 1 _ w r a p C e r t A n d S l o t A n d N i c k n a m e * * Builds a Certificate wrapper around a CERTCertificate, a * PK11SlotInfo, and a nickname. * cert: Will be eaten and erased whether the wrap was successful or not. * slot: Will be eaten and erased whether the wrap was successful or not. * nickname: the cert instance's nickname * returns: a new PK11Cert wrapping the CERTCertificate, PK11SlotInfo, * and nickname, or NULL if an exception was thrown. */ jobject JSS_PK11_wrapCertAndSlotAndNickname(JNIEnv *env, CERTCertificate **cert, PK11SlotInfo **slot, const char *nickname) { jclass certClass; jmethodID constructor; jbyteArray certPtr; jbyteArray slotPtr; jstring jnickname = NULL; jobject Cert=NULL; PR_ASSERT(env!=NULL && cert!=NULL && *cert!=NULL && slot!=NULL); certPtr = JSS_ptrToByteArray(env, *cert); slotPtr = JSS_ptrToByteArray(env, *slot); if (nickname) { jnickname = (*env)->NewStringUTF(env, nickname); } certClass = (*env)->FindClass(env, INTERNAL_TOKEN_CERT_CLASS_NAME); if(certClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } constructor = (*env)->GetMethodID( env, certClass, PLAIN_CONSTRUCTOR, CERT_CONSTRUCTOR_SIG); if(constructor == NULL) { ASSERT_OUTOFMEM(env); goto finish; } /* Call the constructor */ Cert = (*env)->NewObject(env, certClass, constructor, certPtr, slotPtr, jnickname); if(Cert==NULL) { goto finish; } finish: if(Cert==NULL) { CERT_DestroyCertificate(*cert); if(*slot!=NULL) { PK11_FreeSlot(*slot); } } *cert = NULL; *slot = NULL; return Cert; } /**************************************************************** * * J S S _ P K 1 1 _ w r a p C e r t A n d S l o t * * Builds a Certificate wrapper around a CERTCertificate and a * PK11SlotInfo. * cert: Will be eaten and erased whether the wrap was successful or not. * slot: Will be eaten and erased whether the wrap was successful or not. * returns: a new PK11Cert wrapping the CERTCertificate and PK11SlotInfo, * or NULL if an exception was thrown. */ jobject JSS_PK11_wrapCertAndSlot(JNIEnv *env, CERTCertificate **cert, PK11SlotInfo **slot) { return JSS_PK11_wrapCertAndSlotAndNickname(env, cert, slot, (*cert)->nickname); } /**************************************************************** * * J S S _ P K 1 1 _ w r a p C e r t * * Builds a Certificate wrapper around a CERTCertificate. * cert: Will be eaten and erased whether the wrap was successful or not. * returns: a new PK11Cert wrapping the CERTCertificate, or NULL if an * exception was thrown. * * Use JSS_PK11_wrapCertAndSlot instead if it is important for the PK11Cert * object to have the correct slot pointer or the slot pointer is readily * available. */ jobject JSS_PK11_wrapCert(JNIEnv *env, CERTCertificate **cert) { PK11SlotInfo *slot = (*cert)->slot; if(slot != NULL) { slot = PK11_ReferenceSlot(slot); } return JSS_PK11_wrapCertAndSlot(env, cert, &slot); } static ssize_t CERT_LIST_COUNT(CERTCertList *chain) { ssize_t count = -1; CERTCertListNode *node = NULL; if (chain == NULL) { return count; } for (node = CERT_LIST_HEAD(chain); !CERT_LIST_END(node, chain); node = CERT_LIST_NEXT(node)) { count += 1; } return count + 1; } /**************************************************************** * * J S S _ P K 1 1 _ w r a p C e r t C h a i n * * Builds an array of PK11Cert objects from a CERTCertList. * ppChain: Pointer to pointer to CERTCertList. The CERTCertList * will be wrapped in a Java certificate. If this fails, it * will be deleted. In any case, the caller should never worry about, * or use, this CERTCertList again. To enforce this, *ppChain * will be set to NULL whether the functions fails or succeeds. * Returns: a new Java PK11Cert[] object, or NULL if an exception was thrown. */ jobjectArray JSS_PK11_wrapCertChain(JNIEnv *env, CERTCertList **chain) { jobjectArray result = NULL; jobject wrappedCert = NULL; CERTCertListNode *node = NULL; ssize_t count = 0; if (chain == NULL || *chain == NULL) { goto done; } // Since we can't easily resize our jobjectArray once created, walk the // chain and count its length. count = CERT_LIST_COUNT(*chain); if (count <= 0) { goto done; } // Allocate our result structure. result = (*env)->NewObjectArray(env, count, (*env)->FindClass(env, CERT_CLASS_NAME), NULL); count = 0; for (node = CERT_LIST_HEAD((*chain)); !CERT_LIST_END(node, (*chain)); node = CERT_LIST_NEXT(node)) { // Wrap the certificate and insert it into the array. wrappedCert = JSS_PK11_wrapCert(env, &node->cert); (*env)->SetObjectArrayElement(env, result, count, wrappedCert); count += 1; } done: if (chain) { CERT_DestroyCertList(*chain); *chain = NULL; } return result; } /********************************************************************** * PK11Cert.getOwningToken */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11Cert_getOwningToken (JNIEnv *env, jobject this) { PK11SlotInfo *slot; jobject token = NULL; PR_ASSERT(env!=NULL && this!=NULL); /* get the C PK11SlotInfo structure */ if( JSS_PK11_getCertSlotPtr(env, this, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } PR_ASSERT(slot != NULL); /* wrap the slot in a Java PK11Token */ token = JSS_PK11_wrapPK11Token(env, &slot); if(token == NULL) { PR_ASSERT( (*env)->ExceptionOccurred(env) ); goto finish; } finish: return token; } /* * workaround for bug 100791: misspelled function prototypes in pk11func.h */ SECItem* PK11_GetLowLevelKeyIDForCert(PK11SlotInfo*,CERTCertificate*,void*); /********************************************************************** * PK11Cert.getUniqueID */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11Cert_getUniqueID (JNIEnv *env, jobject this) { CERTCertificate *cert; SECItem *id = NULL; jbyteArray byteArray=NULL; PR_ASSERT(env!=NULL && this!=NULL); /************************************************** * Get the CERTCertificate structure **************************************************/ if( JSS_PK11_getCertPtr(env, this, &cert) != PR_SUCCESS) { goto finish; } /*************************************************** * Get the id ***************************************************/ id = PK11_GetLowLevelKeyIDForCert(NULL /*slot*/, cert, NULL/*pinarg*/); if( id == NULL ) { PR_ASSERT(PR_FALSE); goto finish; } /*************************************************** * Write the id to a new byte array ***************************************************/ byteArray = JSS_ToByteArray(env, id->data, id->len); if (byteArray == NULL) { ASSERT_OUTOFMEM(env); goto finish; } finish: if( id != NULL ) { SECITEM_FreeItem(id, PR_TRUE /*freeit*/); } return byteArray; } /********************************************************************** * This is what used to be PK11Cert.getNickname. Kept merely to * satisfy the symbol export file jss.def. */ JNIEXPORT jstring JNICALL Java_org_mozilla_jss_pkcs11_PK11Cert_getNickname (JNIEnv *env, jobject this) { PR_NOT_REACHED("a stub function"); return NULL; } /********************************************************************** * PK11Cert.setTrust */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11Cert_setTrust (JNIEnv *env, jobject this, jint type, jint newTrust) { CERTCertificate *cert; CERTCertTrust trust; PR_ASSERT(env!=NULL && this!=NULL); if( JSS_PK11_getCertPtr(env, this, &cert) != PR_SUCCESS) { return; } if( CERT_GetCertTrust( cert, &trust ) != SECSuccess) { /* cert doesn't have any trust yet, so initialize to 0 */ memset(&trust, 0, sizeof(trust)); } switch(type) { case 0: /* SSL */ trust.sslFlags = newTrust; break; case 1: /* email */ trust.emailFlags = newTrust; break; case 2: /* object signing */ trust.objectSigningFlags = newTrust; break; default: PR_ASSERT(PR_FALSE); return; } if( CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, &trust) != SECSuccess) { PR_ASSERT(PR_FALSE); return; } return; } /********************************************************************** * PK11Cert.getTrust */ JNIEXPORT jint JNICALL Java_org_mozilla_jss_pkcs11_PK11Cert_getTrust (JNIEnv *env, jobject this, jint type) { CERTCertificate *cert; CERTCertTrust trust; PR_ASSERT(env!=NULL && this!=NULL); if( JSS_PK11_getCertPtr(env, this, &cert) != PR_SUCCESS) { return 0; } if( CERT_GetCertTrust( cert, &trust ) != SECSuccess) { PR_ASSERT(PR_FALSE); return 0; } switch(type) { case 0: /* SSL */ return trust.sslFlags; case 1: /* email */ return trust.emailFlags; case 2: /* object signing */ return trust.objectSigningFlags; default: PR_ASSERT(PR_FALSE); return 0; } } /********************************************************************** * PK11Cert.getSerialNumberByteArray */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11Cert_getSerialNumberByteArray (JNIEnv *env, jobject this) { CERTCertificate *cert; if( JSS_PK11_getCertPtr(env, this, &cert) != PR_SUCCESS) { return NULL; } PR_ASSERT(cert->serialNumber.len > 0); PR_ASSERT(cert->serialNumber.data != NULL); return JSS_OctetStringToByteArray(env, &cert->serialNumber); } /********************************************************************** * PK11Cert.getSubjectDNString */ JNIEXPORT jstring JNICALL Java_org_mozilla_jss_pkcs11_PK11Cert_getSubjectDNString (JNIEnv *env, jobject this) { CERTCertificate *cert; char *ascii; if( JSS_PK11_getCertPtr(env, this, &cert) != PR_SUCCESS) { return NULL; } ascii = CERT_NameToAscii(&cert->subject); if( ascii ) { return (*env)->NewStringUTF(env, ascii); } else { return NULL; } } /********************************************************************** * PK11Cert.getIssuerDNString */ JNIEXPORT jstring JNICALL Java_org_mozilla_jss_pkcs11_PK11Cert_getIssuerDNString (JNIEnv *env, jobject this) { CERTCertificate *cert; char *ascii; if( JSS_PK11_getCertPtr(env, this, &cert) != PR_SUCCESS) { return NULL; } ascii = CERT_NameToAscii(&cert->issuer); if( ascii ) { return (*env)->NewStringUTF(env, ascii); } else { return NULL; } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11Cert.java000066400000000000000000000335741412550063600232610ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import java.util.*; import java.math.BigInteger; import java.security.*; import java.security.cert.*; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.netscape.security.x509.X509CertImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class PK11Cert extends java.security.cert.X509Certificate implements org.mozilla.jss.crypto.X509Certificate, java.lang.AutoCloseable { public static Logger logger = LoggerFactory.getLogger(PK11Cert.class); // Internal X509CertImpl to handle java.security.cert.X509Certificate // methods. private X509CertImpl x509 = null; @Override public native byte[] getEncoded() throws CertificateEncodingException; //public native byte[] getUniqueID(); @Override public String getNickname() { return nickname; } @Override public int hashCode() { try { return Arrays.hashCode(getEncoded()); } catch (CertificateEncodingException cee) { throw new RuntimeException(cee.getMessage(), cee); } } @Override public boolean equals(Object other) { if (other == null || !(other instanceof PK11Cert)) { return false; } PK11Cert p_other = (PK11Cert) other; try { return Arrays.equals(getEncoded(), p_other.getEncoded()); } catch (CertificateEncodingException cee) { throw new RuntimeException(cee.getMessage(), cee); } } /** * A class that implements Principal with a String. */ protected static class StringPrincipal implements Principal { public StringPrincipal(String str) { this.str = str; } @Override public boolean equals(Object other) { if( ! (other instanceof StringPrincipal) ) { return false; } return getName().equals( ((StringPrincipal)other).getName() ); } @Override public String getName() { return str; } @Override public int hashCode() { return str.hashCode(); } @Override public String toString() { return str; } protected String str; } @Override public Principal getSubjectDN() { return new StringPrincipal( getSubjectDNString() ); } @Override public Principal getIssuerDN() { return new StringPrincipal( getIssuerDNString() ); } @Override public BigInteger getSerialNumber() { return new BigInteger( getSerialNumberByteArray() ); } protected native byte[] getSerialNumberByteArray(); protected native String getSubjectDNString(); protected native String getIssuerDNString(); @Override public native java.security.PublicKey getPublicKey(); @Override public native int getVersion(); /* Begin methods necessary for java.security.cert.X509Certificate */ @Override public int getBasicConstraints() { try { if (x509 == null) { x509 = new X509CertImpl(getEncoded()); } return x509.getBasicConstraints(); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public boolean[] getKeyUsage() { try { if (x509 == null) { x509 = new X509CertImpl(getEncoded()); } return x509.getKeyUsage(); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public boolean[] getSubjectUniqueID() { try { if (x509 == null) { x509 = new X509CertImpl(getEncoded()); } return x509.getSubjectUniqueID(); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public boolean[] getIssuerUniqueID() { try { if (x509 == null) { x509 = new X509CertImpl(getEncoded()); } return x509.getIssuerUniqueID(); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public byte[] getSigAlgParams() { try { if (x509 == null) { x509 = new X509CertImpl(getEncoded()); } return x509.getSigAlgParams(); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public String getSigAlgName() { try { if (x509 == null) { x509 = new X509CertImpl(getEncoded()); } return x509.getSigAlgName(); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public String getSigAlgOID() { try { if (x509 == null) { x509 = new X509CertImpl(getEncoded()); } return x509.getSigAlgOID(); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public byte[] getSignature() { try { if (x509 == null) { x509 = new X509CertImpl(getEncoded()); } return x509.getSignature(); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public byte[] getTBSCertificate() throws CertificateEncodingException { try { if (x509 == null) { x509 = new X509CertImpl(getEncoded()); } return x509.getTBSCertificate(); } catch (CertificateEncodingException cee) { throw cee; } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public Date getNotAfter() { try { if (x509 == null) { x509 = new X509CertImpl(getEncoded()); } return x509.getNotAfter(); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public Date getNotBefore() { try { if (x509 == null) { x509 = new X509CertImpl(getEncoded()); } return x509.getNotBefore(); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException { try { if (x509 == null) { x509 = new X509CertImpl(getEncoded()); } x509.checkValidity(); } catch (CertificateExpiredException cee) { throw cee; } catch (CertificateNotYetValidException cnyve) { throw cnyve; } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public void checkValidity(Date date) throws CertificateExpiredException, CertificateNotYetValidException { try { if (x509 == null) { x509 = new X509CertImpl(getEncoded()); } x509.checkValidity(date); } catch (CertificateExpiredException cee) { throw cee; } catch (CertificateNotYetValidException cnyve) { throw cnyve; } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public String toString() { try { if (x509 == null) { x509 = new X509CertImpl(getEncoded()); } return x509.toString(); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { try { if (x509 == null) { x509 = new X509CertImpl(getEncoded()); } x509.verify(key); } catch (NoSuchAlgorithmException nsae) { throw nsae; } catch (InvalidKeyException ike) { throw ike; } catch (NoSuchProviderException nspe) { throw nspe; } catch (SignatureException se) { throw se; } catch (CertificateException ce) { throw ce; } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public void verify(PublicKey key, String sigProvider) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException, SignatureException { try { if (x509 == null) { x509 = new X509CertImpl(getEncoded()); } x509.verify(key, sigProvider); } catch (NoSuchAlgorithmException nsae) { throw nsae; } catch (InvalidKeyException ike) { throw ike; } catch (NoSuchProviderException nspe) { throw nspe; } catch (SignatureException se) { throw se; } catch (CertificateException ce) { throw ce; } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public byte[] getExtensionValue(String oid) { try { if (x509 == null) { x509 = new X509CertImpl(getEncoded()); } return x509.getExtensionValue(oid); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public Set getCriticalExtensionOIDs() { try { if (x509 == null) { x509 = new X509CertImpl(getEncoded()); } return x509.getCriticalExtensionOIDs(); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public Set getNonCriticalExtensionOIDs() { try { if (x509 == null) { x509 = new X509CertImpl(getEncoded()); } return x509.getNonCriticalExtensionOIDs(); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public boolean hasUnsupportedCriticalExtension() { try { if (x509 == null) { x509 = new X509CertImpl(getEncoded()); } return x509.hasUnsupportedCriticalExtension(); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public void finalize() throws Throwable { close(); } @Override public void close() throws Exception { if (certProxy != null) { try { certProxy.close(); } finally { certProxy = null; } } // This object also contains a token proxy; these are reference // counted objects and long-lived; freeing them is of little benefit // as they'll persist as long as CryptoManager holds a copy of all // known tokens. However, we still need to attempt to release our // reference to them, otherwise the JVM will persist its reference // to them. if (tokenProxy != null) { try { tokenProxy.close(); } finally { tokenProxy = null; } } } /////////////////////////////////////////////////////////////////////// // PKCS #11 Cert stuff. Must only be called on certs that have // an associated slot. /////////////////////////////////////////////////////////////////////// protected native byte[] getUniqueID(); protected native CryptoToken getOwningToken(); /////////////////////////////////////////////////////////////////////// // Trust Management. Must only be called on certs that live in the // internal database. /////////////////////////////////////////////////////////////////////// /** * Sets the trust flags for this cert. * * @param type SSL, EMAIL, or OBJECT_SIGNING. * @param trust The trust flags for this type of trust. */ protected native void setTrust(int type, int trust); /** * Gets the trust flags for this cert. * * @param type SSL, EMAIL, or OBJECT_SIGNING. * @return The trust flags for this type of trust. */ protected native int getTrust(int type); ///////////////////////////////////////////////////////////// // Construction ///////////////////////////////////////////////////////////// //PK11Cert(CertProxy proxy) { // assert(proxy!=null); // this.certProxy = proxy; //} PK11Cert(byte[] certPtr, byte[] slotPtr, String nickname) { assert(certPtr!=null); assert(slotPtr!=null); certProxy = new CertProxy(certPtr); tokenProxy = new TokenProxy(slotPtr); this.nickname = nickname; } ///////////////////////////////////////////////////////////// // private data ///////////////////////////////////////////////////////////// protected CertProxy certProxy; protected TokenProxy tokenProxy; protected String nickname; } class CertProxy extends org.mozilla.jss.util.NativeProxy { public static Logger logger = LoggerFactory.getLogger(CertProxy.class); public CertProxy(byte[] pointer) { super(pointer); } @Override protected native void releaseNativeResources(); } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11Cipher.c000066400000000000000000000220021412550063600230570ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "_jni/org_mozilla_jss_pkcs11_PK11Cipher.h" #include #include #include #include #include /* JSS includes */ #include #include #include #include #include /*********************************************************************** * * PK11Cipher.initContext */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11Cipher_initContext (JNIEnv *env, jclass clazz, jboolean encrypt, jobject keyObj, jobject algObj, jbyteArray ivBA, jboolean padded) { return Java_org_mozilla_jss_pkcs11_PK11Cipher_initContextWithKeyBits ( env, clazz, encrypt, keyObj, algObj, ivBA, 0, padded); } JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11Cipher_initContextWithKeyBits (JNIEnv *env, jclass clazz, jboolean encrypt, jobject keyObj, jobject algObj, jbyteArray ivBA, jint keyBits, jboolean padded) { CK_MECHANISM_TYPE mech; PK11SymKey *key=NULL; SECItem *param=NULL; SECItem *iv=NULL; PK11Context *context=NULL; CK_ATTRIBUTE_TYPE op; jobject contextObj = NULL; PR_ASSERT(env!=NULL && clazz!=NULL && keyObj!=NULL && algObj!=NULL); /* get mechanism */ mech = JSS_getPK11MechFromAlg(env, algObj); if(mech == CKM_INVALID_MECHANISM) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to resolve algorithm to" " PKCS #11 mechanism"); goto finish; } if (padded) mech = PK11_GetPadMechanism(mech); /* get operation type */ if( encrypt ) { op = CKA_ENCRYPT; } else { op = CKA_DECRYPT; } /* get key */ if( JSS_PK11_getSymKeyPtr(env, keyObj, &key) != PR_SUCCESS) { goto finish; } /* get param, if there is one */ if( ivBA != NULL ) { iv = JSS_ByteArrayToSECItem(env, ivBA); if( iv == NULL ) { /* exception was thrown */ goto finish; } } param = PK11_ParamFromIV(mech, iv); /* * Set RC2 effective key length. */ if( mech == CKM_RC2_CBC || mech == CKM_RC2_CBC_PAD ) { ((CK_RC2_CBC_PARAMS*)param->data)->ulEffectiveBits = keyBits; } /* create crypto context */ context = PK11_CreateContextBySymKey(mech, op, key, param); if(context == NULL ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to generate crypto context"); goto finish; } /* wrap crypto context. This sets context to NULL. */ contextObj = JSS_PK11_wrapCipherContextProxy(env, &context); finish: if( param != NULL ) { SECITEM_FreeItem(param, PR_TRUE /*freeit*/); } if(iv) { SECITEM_FreeItem(iv, PR_TRUE /*freeit*/); } if(context != NULL) { /* if the function succeeded, context would be NULL */ PK11_DestroyContext(context, PR_TRUE /*freeit*/); } PR_ASSERT( contextObj || (*env)->ExceptionOccurred(env) ); return contextObj; } /*********************************************************************** * * PK11Cipher.updateContext */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11Cipher_updateContext (JNIEnv *env, jclass clazz, jobject contextObj, jbyteArray inputBA, jint blockSize) { PK11Context *context=NULL; jbyte *inbuf=NULL; unsigned int inlen; unsigned char *outbuf=NULL; unsigned int outlen; jbyteArray outArray=NULL; PR_ASSERT(env!=NULL && clazz!=NULL && contextObj!=NULL && inputBA!=NULL); /* get the context */ if( JSS_PK11_getCipherContext(env, contextObj, &context) != PR_SUCCESS) { goto finish; } /* extract input from byte array */ inlen = (*env)->GetArrayLength(env, inputBA); inbuf = (*env)->GetByteArrayElements(env, inputBA, NULL); if(inbuf == NULL) { ASSERT_OUTOFMEM(env); goto finish; } /* create output buffer */ outlen = inlen + blockSize; /* this will hold the output */ outbuf = PR_Malloc(outlen); if(outbuf == NULL) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } /* do the operation */ if( PK11_CipherOp(context, outbuf, (int*)&outlen, outlen, (unsigned char*)inbuf, inlen) != SECSuccess) { JSS_throwMsgPrErrArg( env, TOKEN_EXCEPTION, "Cipher context update failed", PR_GetError()); goto finish; } /* convert output buffer to byte array */ outArray = JSS_ToByteArray(env, outbuf, outlen); if (outArray == NULL) { ASSERT_OUTOFMEM(env); goto finish; } finish: if(outbuf) { PR_Free(outbuf); } if (inbuf) { (*env)->ReleaseByteArrayElements(env, inputBA, inbuf, JNI_ABORT); } return outArray; } /*********************************************************************** * * PK11Cipher.finalizeContext * */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11Cipher_finalizeContext (JNIEnv *env, jclass clazz, jobject contextObj, jint blockSize, jboolean padded) { PK11Context *context=NULL; unsigned char *outBuf = NULL; unsigned int outLen, newOutLen; jobject outBA=NULL; SECStatus status; PR_ASSERT(env!=NULL && contextObj!=NULL); /* get context */ if( JSS_PK11_getCipherContext(env, contextObj, &context) != PR_SUCCESS) { goto finish; } /* create output buffer */ outLen = blockSize; /* maximum amount needed */ outBuf = PR_Malloc(outLen); if(outBuf == NULL) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } /* perform the finalization */ status = PK11_DigestFinal(context, outBuf, &newOutLen, outLen); if( (status != SECSuccess) ) { JSS_throwMsgPrErrArg( env, TOKEN_EXCEPTION, "Cipher context finalization failed", PR_GetError()); goto finish; } /* convert output buffer to byte array */ outBA = JSS_ToByteArray(env, outBuf, newOutLen); if(outBA == NULL) { ASSERT_OUTOFMEM(env); goto finish; } finish: if(outBuf) { PR_Free(outBuf); } PR_ASSERT( outBA || (*env)->ExceptionOccurred(env) ); return outBA; } /*********************************************************************** * * J S S _ P K 1 1 _ g e t C i p h e r C o n t e x t * * Extracts the PK11Context from a CipherContextProxy. * * proxy * A CipherContextProxy. * * pContext * Address of a PK11Context*, which will be filled with the pointer * extracted from the CipherContextProxy. * * RETURNS * PR_SUCCESS for success, or PR_FAILURE if an exception was thrown. */ PRStatus JSS_PK11_getCipherContext(JNIEnv *env, jobject proxy, PK11Context **pContext) { PR_ASSERT(env!=NULL && proxy!=NULL && pContext!=NULL); return JSS_getPtrFromProxy(env, proxy, (void**)pContext); } /*********************************************************************** * * J S S _ P K 1 1 _ m a k e C i p h e r C o n t e x t P r o x y * * Wraps a PK11Context in a CipherContextProxy. * * context * address of a pointer to a PK11Context, which must not be NULL. * It will be eaten by the wrapper and set to NULL, even if the * function returns NULL. * * RETURNS * A new CipherContextProxy, or NULL if an exception was thrown. */ jobject JSS_PK11_wrapCipherContextProxy(JNIEnv *env, PK11Context **context) { jbyteArray pointer=NULL; jclass proxyClass; jmethodID constructor; jobject contextObj=NULL; PR_ASSERT( env!=NULL && context!=NULL && *context!=NULL ); /* convert pointer to byte array */ pointer = JSS_ptrToByteArray(env, *context); /* * Lookup the class and constructor */ proxyClass = (*env)->FindClass(env, CIPHER_CONTEXT_PROXY_CLASS_NAME); if(proxyClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } constructor = (*env)->GetMethodID(env, proxyClass, PLAIN_CONSTRUCTOR, CIPHER_CONTEXT_PROXY_CONSTRUCTOR_SIG); if(constructor == NULL) { ASSERT_OUTOFMEM(env); goto finish; } /* call the constructor */ contextObj = (*env)->NewObject(env, proxyClass, constructor, pointer); finish: if(contextObj == NULL) { /* didn't work, so free resources */ PK11_DestroyContext( (PK11Context*)*context, PR_TRUE /*freeit*/ ); } *context=NULL; PR_ASSERT( contextObj || (*env)->ExceptionOccurred(env) ); return contextObj; } /*********************************************************************** * * CipherContextProxy.releaseNativeResources */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_CipherContextProxy_releaseNativeResources (JNIEnv *env, jobject this) { PK11Context *context; if (JSS_PK11_getCipherContext(env, this, &context) == PR_SUCCESS && context != NULL) { PK11_DestroyContext(context, PR_TRUE /*freeit*/); } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11Cipher.java000066400000000000000000000223741412550063600235720ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.BadPaddingException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.RC2ParameterSpec; import org.mozilla.jss.crypto.EncryptionAlgorithm; import org.mozilla.jss.crypto.IVParameterSpec; import org.mozilla.jss.crypto.IllegalBlockSizeException; import org.mozilla.jss.crypto.SymmetricKey; import org.mozilla.jss.crypto.TokenException; public final class PK11Cipher extends org.mozilla.jss.crypto.Cipher implements java.lang.AutoCloseable { // set once in the constructor private PK11Token token; // set once in the constructor private EncryptionAlgorithm algorithm; // set with initXXX() private AlgorithmParameterSpec parameters=null; // set with initXXX() private SymmetricKey key=null; // set with initXXX() private byte[] IV=null; // set with initXXX() private CipherContextProxy contextProxy = null; // modified by various operations private int state=UNINITIALIZED; // States private static final int UNINITIALIZED=0; private static final int ENCRYPT=1; private static final int DECRYPT=2; private PK11Cipher() { } PK11Cipher(PK11Token token, EncryptionAlgorithm algorithm) { this.token = token; this.algorithm = algorithm; } @Override public void initEncrypt(SymmetricKey key) throws InvalidKeyException, InvalidAlgorithmParameterException, TokenException { initEncrypt(key, null); } @Override public void initDecrypt(SymmetricKey key) throws InvalidKeyException, InvalidAlgorithmParameterException, TokenException { initDecrypt(key, null); } private static byte[] getIVFromParams(AlgorithmParameterSpec params) { byte[] IV = null; if( params instanceof IVParameterSpec ) { IV = ((IVParameterSpec)params).getIV(); } else if( params instanceof IvParameterSpec ) { IV = ((IvParameterSpec)params).getIV(); } else if( params instanceof RC2ParameterSpec ) { IV = ((RC2ParameterSpec)params).getIV(); } return IV; } /** * @deprecated isPadded() in EncryptionAlgorithm has been deprecated */ @Override @Deprecated public void initEncrypt(SymmetricKey key, AlgorithmParameterSpec parameters) throws InvalidKeyException, InvalidAlgorithmParameterException, TokenException { reset(); checkKey(key); checkParams(parameters); IV = getIVFromParams(parameters); this.key = key; this.parameters = parameters; state = ENCRYPT; if( parameters instanceof RC2ParameterSpec ) { contextProxy = initContextWithKeyBits( true, key, algorithm, IV, ((RC2ParameterSpec)parameters).getEffectiveKeyBits(), algorithm.isPadded()); } else { contextProxy = initContext( true, key, algorithm, IV, algorithm.isPadded()); } } /** * @deprecated isPadded() in EncryptionAlgorithm has been deprecated */ @Override @Deprecated public void initDecrypt(SymmetricKey key, AlgorithmParameterSpec parameters) throws InvalidKeyException, InvalidAlgorithmParameterException, TokenException { reset(); checkKey(key); checkParams(parameters); IV = getIVFromParams(parameters); this.key = key; this.parameters = parameters; state = DECRYPT; if( parameters instanceof RC2ParameterSpec ) { contextProxy = initContextWithKeyBits( false, key, algorithm, IV, ((RC2ParameterSpec)parameters).getEffectiveKeyBits(), algorithm.isPadded()); } else { contextProxy = initContext( false, key, algorithm, IV, algorithm.isPadded()); } } @Override public byte[] update(byte[] bytes) throws IllegalStateException, TokenException { if( state == UNINITIALIZED ) { throw new IllegalStateException(); } return updateContext( contextProxy, bytes, algorithm.getBlockSize()); } @Override public byte[] update(byte[] bytes, int offset, int length) throws IllegalStateException, TokenException { byte[] sub = new byte[length]; System.arraycopy( bytes, offset, sub, 0, length ); return update(sub); } /** * @deprecated isPadded() in EncryptionAlgorithm has been deprecated */ @Override @Deprecated public byte[] doFinal(byte[] bytes) throws IllegalStateException, IllegalBlockSizeException, BadPaddingException, TokenException { if( state == UNINITIALIZED ) { throw new IllegalStateException(); } byte[] first = update(bytes); byte[] last = finalizeContext(contextProxy, algorithm.getBlockSize(), algorithm.isPadded() ); byte[] combined = new byte[ first.length+last.length ]; System.arraycopy(first, 0, combined, 0, first.length); System.arraycopy(last, 0, combined, first.length, last.length); return combined; } @Override public byte[] doFinal(byte[] bytes, int offset, int length) throws IllegalStateException, IllegalBlockSizeException, BadPaddingException, TokenException { byte[] sub = new byte[length]; System.arraycopy(bytes, offset, sub, 0, length); return doFinal(sub); } /** * @deprecated isPadded() in EncryptionAlgorithm has been deprecated */ @Override @Deprecated public byte[] doFinal() throws IllegalStateException, IllegalBlockSizeException, BadPaddingException, TokenException { if( state == UNINITIALIZED ) { throw new IllegalStateException(); } return finalizeContext(contextProxy, algorithm.getBlockSize(), algorithm.isPadded() ); } private static native CipherContextProxy initContext(boolean encrypt, SymmetricKey key, EncryptionAlgorithm alg, byte[] IV, boolean padded) throws TokenException; // This version accepts the number of effective key bits for RC2 CBC. private static native CipherContextProxy initContextWithKeyBits(boolean encrypt, SymmetricKey key, EncryptionAlgorithm alg, byte[] IV, int keyBits, boolean padded) throws TokenException; private static native byte[] updateContext( CipherContextProxy context, byte[] input, int blocksize ) throws TokenException; private static native byte[] finalizeContext( CipherContextProxy context, int blocksize, boolean padded) throws TokenException, IllegalBlockSizeException, BadPaddingException; private void reset() { parameters = null; key = null; IV = null; state = UNINITIALIZED; contextProxy = null; } /** * Matches the params against those expected by the algorithm. */ private void checkParams(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException { if( ! algorithm.isValidParameterObject(params) ) { String name = "null"; if( params != null ) { name = params.getClass().getName(); } throw new InvalidAlgorithmParameterException(algorithm + " cannot use a " + name + " parameter"); } } /** * Checks for null, makes sure the key lives on the correct token, * makes sure it is a PKCS #11 key, makes sure it's the right type * for this algorithm. */ private void checkKey(SymmetricKey key) throws InvalidKeyException { if( key==null ) { throw new InvalidKeyException("Key is null"); } if( ! (key instanceof PK11SymKey) ) { throw new InvalidKeyException("Key is not a PKCS #11 key"); } try { KeyType keyType = ((PK11SymKey) key).getKeyType(); if ( keyType != KeyType.GENERIC_SECRET && keyType != KeyType.getKeyTypeFromAlgorithm(algorithm) ) { throw new InvalidKeyException("Key is not the right type for"+ " this algorithm. Got: " + ((PK11SymKey)key).getKeyType() + " Expected: " + KeyType.getKeyTypeFromAlgorithm(algorithm)); } } catch( NoSuchAlgorithmException e ) { throw new RuntimeException("Unknown algorithm: " + algorithm, e); } } @Override public void finalize() throws Throwable { close(); } @Override public void close() throws Exception { if (contextProxy != null) { try { contextProxy.close(); } finally { contextProxy = null; } } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11DSAPrivateKey.java000066400000000000000000000020301412550063600247560ustar00rootroot00000000000000package org.mozilla.jss.pkcs11; import org.mozilla.jss.crypto.PrivateKey; import org.mozilla.jss.crypto.TokenException; import java.math.BigInteger; import java.security.interfaces.DSAParams; import java.security.interfaces.DSAPrivateKey; public class PK11DSAPrivateKey extends PK11PrivKey implements DSAPrivateKey { private static final long serialVersionUID = 1L; private PK11DSAPrivateKey() { super(null); } protected PK11DSAPrivateKey(byte[] pointer) { super(pointer); } @Override public PrivateKey.Type getType() { return PrivateKey.Type.DSA; } /** * If this fails, we just return null, since no exceptions are allowed. */ @Override public DSAParams getParams() { try { return getDSAParams(); } catch(TokenException te) { return null; } } /** * Not implemented. NSS doesn't support extracting private key material * like this. */ @Override public BigInteger getX() { return null; } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11DSAPublicKey.java000066400000000000000000000027141412550063600245730ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import java.math.BigInteger; import java.security.interfaces.DSAParams; import java.security.interfaces.DSAPublicKey; import java.security.spec.DSAParameterSpec; public final class PK11DSAPublicKey extends PK11PubKey implements DSAPublicKey { private static final long serialVersionUID = 1L; public PK11DSAPublicKey(byte[] pointer) { super(pointer); } @Override public DSAParams getParams() { try { BigInteger P = new BigInteger( getPByteArray() ); BigInteger Q = new BigInteger( getQByteArray() ); BigInteger G = new BigInteger( getGByteArray() ); return new DSAParameterSpec(P, Q, G); } catch(NumberFormatException e) { throw new RuntimeException("Unable to decode DSA parameters: " + e.getMessage(), e); } } @Override public BigInteger getY() { try { return new BigInteger( getYByteArray() ); } catch(NumberFormatException e) { throw new RuntimeException("Unable to decode DSA public value: " + e.getMessage(), e); } } private native byte[] getPByteArray(); private native byte[] getQByteArray(); private native byte[] getGByteArray(); private native byte[] getYByteArray(); } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11ECPrivateKey.java000066400000000000000000000022151412550063600246430ustar00rootroot00000000000000package org.mozilla.jss.pkcs11; import java.security.interfaces.ECPrivateKey; import java.security.spec.ECParameterSpec; import java.math.BigInteger; import org.mozilla.jss.crypto.PrivateKey; public class PK11ECPrivateKey extends PK11PrivKey implements ECPrivateKey { private static final long serialVersionUID = 1L; private PK11ECPrivateKey() { super(null); } protected PK11ECPrivateKey(byte[] pointer) { super(pointer); } @Override public PrivateKey.Type getType() { return PrivateKey.Type.EC; } @Override public ECParameterSpec getParams() { PK11PubKey publicKey = getPublicKey(); if (!(publicKey instanceof PK11ECPublicKey)) { throw new RuntimeException("Unknown key type: expected the public key of an EC key to be an PK11ECPublicKey; got: " + publicKey); } PK11ECPublicKey ecPublicKey = (PK11ECPublicKey)publicKey; return ecPublicKey.getParams(); } /** * Not implemented. NSS doesn't support extracting private key material * like this. */ @Override public BigInteger getS() { return null; } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11ECPublicKey.java000066400000000000000000000020461412550063600244510ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import java.security.interfaces.ECPublicKey; import java.security.spec.ECPoint; import java.security.spec.ECParameterSpec; import org.mozilla.jss.util.EC; public final class PK11ECPublicKey extends PK11PubKey implements ECPublicKey { private static final long serialVersionUID = 1L; public PK11ECPublicKey(byte[] pointer) { super(pointer); } @Override public ECParameterSpec getParams() { byte[] curveData = getCurveByteArray(); return EC.decodeNSSOID(curveData); } public byte[] getCurveBA() { return getCurveByteArray(); } @Override public ECPoint getW() { byte[] pointData = getWByteArray(); return EC.decodeNSSPoint(pointData); } private native byte[] getCurveByteArray(); public native byte[] getWByteArray(); } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11Exception.java000066400000000000000000000015251412550063600243110ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; /** * This is a generic PKCS #11 exception. */ public class PK11Exception extends RuntimeException { private static final long serialVersionUID = 1L; public PK11Exception() { } public PK11Exception(String mesg) { super(mesg); } public PK11Exception(Throwable cause) { super(cause); } public PK11Exception(String mesg, Throwable cause) { super(mesg, cause); } public PK11Exception(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(mesg, cause, enableSuppression, writableStackTrace); } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11InternalCert.java000066400000000000000000000056201412550063600247450ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import org.mozilla.jss.crypto.*; /** * A certificate that lives in the internal cert database. */ public class PK11InternalCert extends PK11Cert implements InternalCertificate { /////////////////////////////////////////////////////////////////////// // Trust Management. This is all package stuff because it can only // be called from PK11InternalCert. /////////////////////////////////////////////////////////////////////// public static final int SSL = 0; public static final int EMAIL = 1; public static final int OBJECT_SIGNING=2; /** * Set the SSL trust flags for this certificate. * * @param trust A bitwise OR of the trust flags VALID_PEER, VALID_CA, * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. */ @Override public void setSSLTrust(int trust) { super.setTrust(SSL, trust); } /** * Set the email (S/MIME) trust flags for this certificate. * * @param trust A bitwise OR of the trust flags VALID_PEER, VALID_CA, * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. */ @Override public void setEmailTrust(int trust) { super.setTrust(EMAIL, trust); } /** * Set the object signing trust flags for this certificate. * * @param trust A bitwise OR of the trust flags VALID_PEER, VALID_CA, * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. */ @Override public void setObjectSigningTrust(int trust) { super.setTrust(OBJECT_SIGNING, trust); } /** * Get the SSL trust flags for this certificate. * * @return A bitwise OR of the trust flags VALID_PEER, VALID_CA, * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. */ @Override public int getSSLTrust() { return super.getTrust(SSL); } /** * Get the email (S/MIME) trust flags for this certificate. * * @return A bitwise OR of the trust flags VALID_PEER, VALID_CA, * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. */ @Override public int getEmailTrust() { return super.getTrust(EMAIL); } /** * Get the object signing trust flags for this certificate. * * @return A bitwise OR of the trust flags VALID_PEER, VALID_CA, * TRUSTED_CA, USER, and TRUSTED_CLIENT_CA. */ @Override public int getObjectSigningTrust() { return super.getTrust(OBJECT_SIGNING); } ///////////////////////////////////////////////////////////// // Construction ///////////////////////////////////////////////////////////// PK11InternalCert(byte[] certPtr, byte[] slotPtr, String nickname) { super(certPtr, slotPtr, nickname); } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11InternalTokenCert.java000066400000000000000000000015241412550063600257450ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import org.mozilla.jss.crypto.*; /** * A certificate that lives on the internal token. It has database information * (like trust flags) but also PKCS #11 information (like unique ID). */ public final class PK11InternalTokenCert extends PK11InternalCert implements TokenCertificate { @Override public byte[] getUniqueID() { return super.getUniqueID(); } @Override public CryptoToken getOwningToken() { return super.getOwningToken(); } PK11InternalTokenCert(byte[] certPtr, byte[] slotPtr, String nickname) { super(certPtr, slotPtr, nickname); } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11Key.java000066400000000000000000000044011412550063600230770ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.IOException; import org.mozilla.jss.util.AssertionException; abstract class PK11Key implements java.security.Key, java.lang.AutoCloseable { ////////////////////////////////////////////////////////// // Public Interface /////////////////////////////////////////////////////////// /** * Subclasses that support encoding can overload this method. */ @Override public byte[] getEncoded() { return null; } /** * Subclasses that support encoding can overload this method. */ @Override public String getFormat() { return null; } ///////////////////////////////////////////////////////////// // Construction ///////////////////////////////////////////////////////////// protected PK11Key() {} ///////////////////////////////////////////////////////////// // Implementation ///////////////////////////////////////////////////////////// // **HACK** // Override serialization methods so that we don't get serialized, // even though we are supposed to support it as an implementation of Key. private void writeObject(ObjectOutputStream out) throws IOException { throw new AssertionException("PKCS#11 Key is not really serializable"); } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { throw new AssertionException("PKCS#11 Key is not really serializable"); } ///////////////////////////////////////////////////////////// // Members ///////////////////////////////////////////////////////////// protected KeyProxy keyProxy; @Override public void finalize() throws Throwable { close(); } @Override public void close() throws Exception { if (keyProxy != null) { try { keyProxy.close(); } finally { keyProxy = null; } } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11KeyGenerator.c000066400000000000000000000352211412550063600242530ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "_jni/org_mozilla_jss_pkcs11_PK11KeyGenerator.h" #include #include #include #include #include #include /* for hand-generating SHA-1 PBA HMAC key */ #include #include "jssutil.h" #include "pk11util.h" #include "StaticVoidPointer.h" #include #include #include #include #include /*********************************************************************** * * PK11KeyGenerator.generateNormal * * Generates a non-PBE symmetric key on a token. * */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11KeyGenerator_generateNormal (JNIEnv *env, jclass clazz, jobject token, jobject alg, jint strength, jint opFlags, jboolean temporary, jint sensitive) { PK11SlotInfo *slot=NULL; PK11SymKey *skey=NULL; CK_MECHANISM_TYPE mech; PK11AttrFlags attrFlags=0; jobject keyObj=NULL; PR_ASSERT( env!=NULL && clazz!=NULL && token!=NULL && alg!=NULL ); /* Get the slot */ if( JSS_PK11_getTokenSlotPtr(env, token, &slot) != PR_SUCCESS ) { goto finish; } /* Get the algorithm info */ mech = JSS_getPK11MechFromAlg(env, alg); PR_ASSERT(mech != CKM_INVALID_MECHANISM); if(!temporary) { attrFlags |= (PK11_ATTR_TOKEN | PK11_ATTR_PRIVATE); } if(sensitive==1) { attrFlags |= PK11_ATTR_SENSITIVE; } else if(sensitive==0) { attrFlags |= PK11_ATTR_INSENSITIVE; } /* generate the key */ skey = PK11_TokenKeyGenWithFlags(slot, mech, NULL /*param*/, strength/8 /*in bytes*/, NULL /*keyid*/, opFlags, attrFlags, NULL /*wincx*/ ); if(skey==NULL) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "KeyGen failed on token"); goto finish; } /* wrap the key. This sets skey to NULL. */ keyObj = JSS_PK11_wrapSymKey(env, &skey); finish: if(skey!=NULL) { /* will only be non-NULL if keygen succeeded but wrapSymKey failed */ PK11_FreeSymKey(skey); } return keyObj; } /* We do the translation in Java now, but I'll leave this here just in case */ #if 0 /*********************************************************************** * * C o p y P a s s w o r d T o S E C I t e m * * pass * A Java Password object. * * RETURNS * A new SECItem containing a copy of the bytes in the password, * or NULL iff an exception occurred. Be sure to zero it when * you free it. */ static SECItem* CopyPasswordToSECItem(JNIEnv *env, jobject pass) { jclass passClass=NULL; jmethodID byteCopyMethod=NULL; jbyteArray pwArray=NULL; jbyte *bytes=NULL; SECItem *item=NULL; int numBytes=0; PR_ASSERT(env!=NULL && pass!=NULL); /* get password class and method */ passClass = (*env)->GetObjectClass(env, pass); if(passClass == NULL) { JSS_trace(env, JSS_TRACE_ERROR, "Failed to find Password class"); ASSERT_OUTOFMEM(env); goto finish; } byteCopyMethod = (*env)->GetMethodID( env, passClass, PW_GET_BYTE_COPY_NAME, PW_GET_BYTE_COPY_SIG); if(byteCopyMethod==NULL) { JSS_trace(env, JSS_TRACE_ERROR, "Failed to find Password manipulation" " methods from native implementation"); ASSERT_OUTOFMEM(env); goto finish; } /* copy to a byte array */ pwArray = (*env)->CallObjectMethod(env, pass, byteCopyMethod); if(pwArray == NULL) { ASSERT_OUTOFMEM(env); goto finish; } numBytes = (*env)->GetArrayLength(env, pwArray); /* copy from the byte array to a jbyte array */ bytes = (*env)->GetByteArrayElements(env, pwArray, NULL); if(bytes == NULL) { ASSERT_OUTOFMEM(env); goto finish; } /* copy from the jbyte array to a new SECItem */ item = PR_NEW(SECItem); /* last byte is null termination */ PR_ASSERT( bytes[numBytes-1] == 0 ); item->len = numBytes - 1; item->data = PR_Malloc(item->len); if(item->data==NULL) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } memcpy(item->data, bytes, item->len); finish: if(bytes!=NULL) { /* clear the password */ PR_ASSERT(numBytes > 0); memset(bytes, 0, numBytes); (*env)->ReleaseByteArrayElements(env, pwArray, bytes, 0); } else { PR_ASSERT(pwArray!=NULL); } return item; } #endif static void FUNCTION_MAY_NOT_BE_USED print_secitem(SECItem *item) { unsigned int i; unsigned int online; if(item==NULL) { return; } for(i=0, online=0; i < item->len; i++, online++) { if(online > 25) { printf("\n"); online = 0; } printf("%.2x ", item->data[i]); } } /*********************************************************************** * * c o n s t r u c t S H A 1 P B A K e y * * Constructs a PBE key using CKM_PBA_SHA1_WITH_SHA1_HMAC. This should * be supported by NSS automatically, but isn't (bug #336587). * * RETURNS * A symmetric key from the given password, salt, and iteration count, * or NULL if an exception was thrown. * THROWS * TokenException if an error occurs. */ static PK11SymKey* constructSHA1PBAKey(JNIEnv *env, PK11SlotInfo *slot, SECItem *pwitem, SECItem *salt, int iterationCount) { PK11SymKey *key=NULL; unsigned char ivData[8]; SECItem mechItem; CK_PBE_PARAMS pbe_params; if( pwitem == NULL ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "constructSHA1PAKey:" " pwitem NULL"); goto finish; } if( salt == NULL ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "constructSHA1PAKey:" " salt NULL"); goto finish; } pbe_params.pInitVector = ivData; pbe_params.pPassword = pwitem->data; pbe_params.ulPasswordLen = pwitem->len; pbe_params.pSalt = salt->data; pbe_params.ulSaltLen = salt->len; pbe_params.ulIteration = iterationCount; mechItem.data = (unsigned char *) &pbe_params; mechItem.len = sizeof(pbe_params); key = PK11_RawPBEKeyGen(slot, CKM_PBA_SHA1_WITH_SHA1_HMAC, &mechItem, pwitem, PR_FALSE, NULL); if( key == NULL ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "PK11_RawPBEKeyGen:" " failed to generate key"); goto finish; } finish: return key; } /*********************************************************************** * * PK11KeyGenerator.generatePBE * */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11KeyGenerator_generatePBE( JNIEnv *env, jclass clazz, jobject token, jobject alg, jobject encAlg, jbyteArray passBA, jbyteArray saltBA, jint iterationCount) { PK11SlotInfo *slot=NULL; PK11SymKey *skey=NULL; SECOidTag oidTag; SECAlgorithmID *algid=NULL; SECItem *salt=NULL; SECItem *pwitem=NULL; jobject keyObj=NULL; CK_MECHANISM_TYPE mech=CKM_INVALID_MECHANISM; PR_ASSERT(env!=NULL && clazz!=NULL && token!=NULL && alg!=NULL && passBA!=NULL && saltBA!=NULL); /* get the slot */ if( JSS_PK11_getTokenSlotPtr(env, token, &slot) != PR_SUCCESS) { goto finish; } /* convert salt to SECItem */ salt = JSS_ByteArrayToSECItem(env, saltBA); if(salt == NULL) { goto finish; } /* convert password to SECItem */ pwitem = JSS_ByteArrayToSECItem(env, passBA); if(pwitem==NULL) { ASSERT_OUTOFMEM(env); goto finish; } /* print_secitem(pwitem); */ mech = JSS_getPK11MechFromAlg(env, alg); if( mech == CKM_PBA_SHA1_WITH_SHA1_HMAC ) { /* special case, construct key by hand. Bug #336587 */ skey = constructSHA1PBAKey(env, slot, pwitem, salt, iterationCount); if( skey==NULL ) { /* exception was thrown */ goto finish; } } else { /* get the algorithm info */ oidTag = JSS_getOidTagFromAlg(env, alg); PR_ASSERT(oidTag != SEC_OID_UNKNOWN); SECOidTag encAlgOidTag = JSS_getOidTagFromAlg(env, encAlg); PR_ASSERT(encAlgOidTag != SEC_OID_UNKNOWN); /* create algid */ algid = PK11_CreatePBEV2AlgorithmID( oidTag, encAlgOidTag, SEC_OID_HMAC_SHA1, 0, iterationCount, salt); if( algid == NULL ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to process PBE parameters"); goto finish; } /* generate the key */ skey = PK11_PBEKeyGen(slot, algid, pwitem, PR_FALSE /*faulty3DES*/, NULL /*wincx*/); if( skey == NULL ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to generate PBE key"); goto finish; } } /* wrap the key. This sets skey to NULL. */ keyObj = JSS_PK11_wrapSymKey(env, &skey); finish: if(algid) { SECOID_DestroyAlgorithmID(algid, PR_TRUE /*freeit*/); } if(salt) { SECITEM_FreeItem(salt, PR_TRUE /*freeit*/); } if(pwitem) { SECITEM_ZfreeItem(pwitem, PR_TRUE /*freeit*/); } if(skey) { /* skey will be NULL if everything worked */ PK11_FreeSymKey(skey); } return keyObj; } /*********************************************************************** * * PK11KeyGenerator.generatePBE_IV * */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11KeyGenerator_generatePBE_1IV (JNIEnv *env, jclass clazz, jobject alg, jbyteArray passBA, jbyteArray saltBA, jint iterationCount) { SECOidTag oidTag; SECAlgorithmID *algid=NULL; SECItem *salt=NULL; SECItem *pwitem=NULL; SECItem *ivItem=NULL; jbyteArray ivBA=NULL; PR_ASSERT(env!=NULL && clazz!=NULL && alg!=NULL && passBA!=NULL && saltBA!=NULL); /* get the algorithm info */ oidTag = JSS_getOidTagFromAlg(env, alg); PR_ASSERT(oidTag != SEC_OID_UNKNOWN); /* convert salt to SECItem */ salt = JSS_ByteArrayToSECItem(env, saltBA); if(salt == NULL) { goto finish; } /* create algid */ algid = PK11_CreatePBEAlgorithmID(oidTag, iterationCount, salt); if( algid == NULL ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to process PBE parameters"); goto finish; } /* convert password to SECItem */ pwitem = JSS_ByteArrayToSECItem(env, passBA); if(pwitem==NULL) { ASSERT_OUTOFMEM(env); goto finish; } /* generate the IV */ ivItem = SEC_PKCS5GetIV(algid, pwitem, PR_FALSE /*faulty3DES*/); if(ivItem==NULL) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to generate PBE " "initialization vector"); goto finish; } /* convert IV to byte array */ ivBA = JSS_SECItemToByteArray(env, ivItem); finish: if(algid) { SECOID_DestroyAlgorithmID(algid, PR_TRUE /*freeit*/); } if(salt) { SECITEM_FreeItem(salt, PR_TRUE /*freeit*/); } if(pwitem) { SECITEM_ZfreeItem(pwitem, PR_TRUE /*freeit*/); } if(ivItem) { SECITEM_FreeItem(ivItem, PR_TRUE /*freeit*/); } return ivBA; } JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11KeyGenerator_nativeClone (JNIEnv *env, jclass clazz, jobject tokenObj, jobject toBeClonedObj) { PK11SlotInfo *slot=NULL; PK11SymKey *toBeCloned=NULL; PK11SymKey *clone=NULL; SECStatus rv; jobject cloneObj=NULL; PR_ASSERT(env!=NULL && tokenObj!=NULL && toBeClonedObj!=NULL); /* get slot */ if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS) { /* exception was thrown */ goto finish; } /* get toBeCloned */ if( JSS_PK11_getSymKeyPtr(env, toBeClonedObj, &toBeCloned) != PR_SUCCESS) { /* exception was thrown */ goto finish; } /* extract the key value */ rv = PK11_ExtractKeyValue(toBeCloned); if( rv != SECSuccess ) { JSS_throw(env, NOT_EXTRACTABLE_EXCEPTION); goto finish; } clone = PK11_ImportSymKey( slot, PK11_GetMechanism(toBeCloned), PK11_OriginGenerated, /* we don't know this, but it doesn't matter */ CKA_ENCRYPT, /* !!! Actually we want to enable all operations */ PK11_GetKeyData(toBeCloned), NULL /* wincx */ ); if( clone == NULL ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to create new symmetric" " key object"); goto finish; } /* wrap the new key in a Java object */ cloneObj = JSS_PK11_wrapSymKey(env, &clone); finish: if( clone!=NULL ) { /* clone would be NULL if we completed successfully */ PK11_FreeSymKey(clone); } return cloneObj; } /*********************************************************************** * * PK11KeyGenerator.generateKBKDF * */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11KeyGenerator_generateKBKDF(JNIEnv *env, jclass clazz, jobject tokenObj, jobject baseKeyObj, jlong alg, jobject paramsObj, jlong params_size, jlong derivedKeyAlgorithm, jint strength, jint opFlags, jboolean temporary, jint sensitive) { PK11SlotInfo *slot = NULL; PK11SymKey *baseKey = NULL; PK11SymKey *result = NULL; jobject resultObj = NULL; SECItem param_item = { 0 }; void *param_ptr = NULL; PRBool isPerm = PR_FALSE; PR_ASSERT(env != NULL && tokenObj != NULL); /* get slot */ if (JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS) { /* exception was thrown */ goto finish; } /* get base key */ if (JSS_PK11_getSymKeyPtr(env, baseKeyObj, &baseKey) != PR_SUCCESS) { /* exception was thrown */ goto finish; } /* get params */ if (JSS_PR_getStaticVoidRef(env, paramsObj, ¶m_ptr) != PR_SUCCESS) { /* exception was thrown */ goto finish; } param_item.type = siBuffer; param_item.data = (unsigned char *)(param_ptr); param_item.len = (unsigned int) params_size; isPerm = (temporary == JNI_FALSE) ? PR_TRUE : PR_FALSE; result = PK11_DeriveWithFlagsPerm(baseKey, alg, ¶m_item, derivedKeyAlgorithm, CKA_ENCRYPT, strength, opFlags, isPerm); if (result == NULL) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to create derived symmetric key object"); goto finish; } resultObj = JSS_PK11_wrapSymKey(env, &result); finish: PK11_FreeSymKey(result); return resultObj; } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11KeyGenerator.java000066400000000000000000000277671412550063600247720ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import java.io.CharConversionException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.spec.AlgorithmParameterSpec; import org.mozilla.jss.crypto.EncryptionAlgorithm; import org.mozilla.jss.crypto.KBKDFParameterSpec; import org.mozilla.jss.crypto.KeyGenAlgorithm; import org.mozilla.jss.crypto.KeyGenerator; import org.mozilla.jss.crypto.PBEKeyGenParams; import org.mozilla.jss.crypto.SymmetricKey; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.util.NativeProxy; import org.mozilla.jss.util.Password; import org.mozilla.jss.util.UTF8Converter; public final class PK11KeyGenerator implements KeyGenerator { // The token this key will be generated on. private PK11Token token; // The algorithm to use to generate the key private KeyGenAlgorithm algorithm; // The strength of the key to be generated in bits. A value of 0 means // that the strength has not been set. This is OK for most algorithms. private int strength=0; // The parameters for this algorithm. May be null for some algorithms. private AlgorithmParameterSpec parameters; // The crypto operations the key will support. It is the logical OR // of the opFlag constants, each specifying a supported operation. private long opFlags = PKCS11Constants.CKF_SIGN | PKCS11Constants.CKF_ENCRYPT; // Whether the key will be temporary or permanent private boolean temporaryKeyMode = true; // Whether the key will be sensitive or insensitive // 1: sensitive // 0: insensitive // -1: unspecified (token dependent) private int sensitiveKeyMode = -1; // Used to convert Java Password into a byte[]. private KeyGenerator.CharToByteConverter charToByte; private PK11KeyGenerator() { } // package private constructor PK11KeyGenerator(PK11Token token, KeyGenAlgorithm algorithm) { if( token==null || algorithm==null ) { throw new NullPointerException(); } this.token = token; this.algorithm = algorithm; charToByte = new KeyGenerator.CharToByteConverter() { @Override public byte[] convert(char[] chars) throws CharConversionException { return UTF8Converter.UnicodeToUTF8(chars); } }; } /** * Sets the character to byte converter for passwords. The default * conversion is UTF8 with no null termination. */ @Override public void setCharToByteConverter( KeyGenerator.CharToByteConverter charToByte) { if( charToByte==null ) { throw new IllegalArgumentException("CharToByteConverter is null"); } this.charToByte = charToByte; } /** * @param strength Key size in bits. Must be evenly divisible by 8. */ @Override public void initialize(int strength) throws InvalidAlgorithmParameterException { // if this algorithm only accepts PBE key gen params, it can't // use a strength Class[] paramClasses = algorithm.getParameterClasses(); if( paramClasses.length == 1 && paramClasses[0].equals(PBEKeyGenParams.class) ) { throw new InvalidAlgorithmParameterException("PBE keygen "+ "algorithms require PBEKeyGenParams "); } // validate the strength for our algorithm if( ! algorithm.isValidStrength(strength) ) { throw new InvalidAlgorithmParameterException(strength+ " is not a valid strength for "+algorithm); } if( strength % 8 != 0 ) { throw new InvalidAlgorithmParameterException( "Key strength must be divisible by 8"); } this.strength = strength; } @Override public void initialize(AlgorithmParameterSpec parameters) throws InvalidAlgorithmParameterException { if( ! algorithm.isValidParameterObject(parameters) ) { String name = "null"; if( parameters != null ) { name = parameters.getClass().getName(); } throw new InvalidAlgorithmParameterException( algorithm + " cannot use a " + name + " parameter"); } this.parameters = parameters; } @Override public void setKeyUsages(SymmetricKey.Usage[] usages) { this.opFlags = 0; for( int i = 0; i < usages.length; i++ ) { if( usages[i] != null ) { this.opFlags |= usages[i].value(); } } } public void setKeyUsages(long opFlags) { this.opFlags = opFlags; } @Override public void temporaryKeys(boolean temp) { this.temporaryKeyMode = temp; } @Override public void sensitiveKeys(boolean sensitive) { this.sensitiveKeyMode = sensitive ? 1 : 0; } /** * Generates the key. This is the public interface, the actual * work is done by native methods. */ @Override public SymmetricKey generate() throws IllegalStateException, TokenException, CharConversionException { Class[] paramClasses = algorithm.getParameterClasses(); boolean is_pbe = paramClasses.length == 1 && paramClasses[0].equals(PBEKeyGenParams.class); boolean is_kbkdf = paramClasses.length == 1 && parameters instanceof KBKDFParameterSpec; if (is_pbe) { if(parameters==null || !(parameters instanceof PBEKeyGenParams)) { throw new IllegalStateException( "PBE keygen algorithms require PBEKeyGenParams"); } PBEKeyGenParams kgp = (PBEKeyGenParams)parameters; byte[] pwbytes=null; try { pwbytes = charToByte.convert( kgp.getPassword().getChars() ); return generatePBE( token, algorithm, kgp.getEncryptionAlgorithm(), pwbytes, kgp.getSalt(), kgp.getIterations()); } finally { if( pwbytes!=null ) { Password.wipeBytes(pwbytes); } } } else if (is_kbkdf) { KBKDFParameterSpec kps = (KBKDFParameterSpec) parameters; SymmetricKey result = null; try { try { kps.open(); long pkcs11_alg = algorithm.getEnum().getValue(); result = generateKBKDF(token, kps.prfKey, pkcs11_alg, kps.mPointer, kps.mPointerSize, kps.derivedKeyAlgorithm, kps.keySize, (int) opFlags, temporaryKeyMode, sensitiveKeyMode); } finally { kps.close(); } } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } return result; } else { return generateNormal( token, algorithm, strength, (int) opFlags, temporaryKeyMode, sensitiveKeyMode); } } /** * Generates an Initialization Vector using a PBE algorithm. * In order to call this method, the algorithm must be a PBE algorithm, * and the KeyGenerator must have been initialized with an instance * of PBEKeyGenParams. * * @return The initialization vector derived from the password and salt * using the PBE algorithm. */ @Override public byte[] generatePBE_IV() throws TokenException, CharConversionException { Class[] paramClasses = algorithm.getParameterClasses(); boolean is_pbe = paramClasses.length == 1 && paramClasses[0].equals(PBEKeyGenParams.class); if (is_pbe) { if(parameters==null || !(parameters instanceof PBEKeyGenParams)) { throw new IllegalStateException( "PBE keygen algorithms require PBEKeyGenParams"); } PBEKeyGenParams kgp = (PBEKeyGenParams)parameters; byte[] pwbytes=null; try { pwbytes = charToByte.convert(kgp.getPassword().getChars()); return generatePBE_IV(algorithm, pwbytes, kgp.getSalt(), kgp.getIterations() ); } finally { if(pwbytes!=null) { Password.wipeBytes(pwbytes); } } } else { throw new IllegalStateException( "IV generation can only be performed by PBE algorithms"); } } /** * A native method to generate an IV using a PBE algorithm. * None of the parameters should be NULL. */ private static native byte[] generatePBE_IV(KeyGenAlgorithm alg, byte[] password, byte[] salt, int iterations) throws TokenException; /** * Allows a SymmetricKey to be cloned on a different token. * * @exception SymmetricKey.NotExtractableException If the key material * cannot be extracted from the current token. * @exception InvalidKeyException If the owning token cannot process * the key to be cloned. */ @Override public SymmetricKey clone(SymmetricKey key) throws SymmetricKey.NotExtractableException, InvalidKeyException, TokenException { return clone(key, token); } /** * Allows a SymmetricKey to be cloned on a different token. * * @param key The key to clone. * @param token The token on which to clone the key. * @exception SymmetricKey.NotExtractableException If the key material * cannot be extracted from the current token. * @exception InvalidKeyException If the owning token cannot process * the key to be cloned. */ public static SymmetricKey clone(SymmetricKey key, PK11Token token) throws SymmetricKey.NotExtractableException, InvalidKeyException, TokenException { if( ! (key instanceof PK11SymKey) ) { throw new InvalidKeyException("Key is not a PKCS #11 key"); } return nativeClone(token, key); } private static native SymmetricKey nativeClone(PK11Token token, SymmetricKey toBeCloned) throws SymmetricKey.NotExtractableException, TokenException; /** * A native method to generate a non-PBE key. * @param token The token where the key generation happens * @param algorithm The algorithm to use * @param strength The key size in bits, should be 0 for fixed-length * key algorithms. * @param opFlags The crypto operations the key will support * @param temporary Whether the key will be temporary or permanent */ private static native SymmetricKey generateNormal(PK11Token token, KeyGenAlgorithm algorithm, int strength, int opFlags, boolean temporary, int sensitive) throws TokenException; /** * A native method to generate a PBE key. None of the parameters should * be null. */ private static native SymmetricKey generatePBE( PK11Token token, KeyGenAlgorithm algorithm, EncryptionAlgorithm encAlg, byte[] pass, byte[] salt, int iterationCount) throws TokenException; /** * A native method to generate a key using KBKDF. None of the parameters * should be null. */ private static native SymmetricKey generateKBKDF(PK11Token token, PK11SymKey baseKeyObj, long algorithm, NativeProxy pointer, long pointer_size, long derivedKeyAlgorithm, int strength, int opFlags, boolean temporary, int sensitive) throws TokenException; } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11KeyPairGenerator.c000066400000000000000000000363351412550063600250760ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "_jni/org_mozilla_jss_pkcs11_PK11KeyPairGenerator.h" #include #include #include #include #include #include #include #include #include #include /*********************************************************************** * * k e y s T o K e y P a i r * * Turns a SECKEYPrivateKey and a SECKEYPublicKey into a Java KeyPair * object. * * INPUTS * pPrivk * Address of a SECKEYPrivateKey* which will be consumed by the * KeyPair. The pointer will be set to NULL. It is not necessary * to free this private key if the function exits successfully. * pPubk * Address of a SECKEYPublicKey* which will be consumed by this * KeyPair. The pointer will be set to NULL. It is not necessary * to free this public key if the function exits successfully. */ static jobject keysToKeyPair(JNIEnv *env, SECKEYPrivateKey **pPrivk, SECKEYPublicKey **pPubk) { jobject privateKey; jobject publicKey; jobject keyPair=NULL; jclass keyPairClass; jmethodID keyPairConstructor; /************************************************** * wrap the keys in Java objects *************************************************/ publicKey = JSS_PK11_wrapPubKey(env, pPubk); privateKey = JSS_PK11_wrapPrivKey(env, pPrivk); if(publicKey==NULL || privateKey==NULL) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } /************************************************** * encapsulate the keys in a keypair *************************************************/ keyPairClass = (*env)->FindClass(env, KEY_PAIR_CLASS_NAME); if(keyPairClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } keyPairConstructor = (*env)->GetMethodID( env, keyPairClass, KEY_PAIR_CONSTRUCTOR_NAME, KEY_PAIR_CONSTRUCTOR_SIG); if(keyPairConstructor == NULL) { ASSERT_OUTOFMEM(env); goto finish; } keyPair = (*env)->NewObject(env, keyPairClass, keyPairConstructor, publicKey, privateKey); if(keyPair == NULL) { ASSERT_OUTOFMEM(env); goto finish; } finish: return keyPair; } int PK11_NumberObjectsFor(PK11SlotInfo*, CK_ATTRIBUTE*, int); SECStatus JSS_PK11_generateKeyPairWithOpFlags(JNIEnv *env, CK_MECHANISM_TYPE mechanism, PK11SlotInfo *slot, SECKEYPublicKey **pubk, SECKEYPrivateKey **privk, void *params, PRBool temporary, jint sensitive, jint extractable, jint op_flags, jint op_flags_mask) { PK11AttrFlags attrFlags = 0; *privk=NULL; *pubk=NULL; PR_ASSERT(env!=NULL && slot!=NULL); /************************************************** * login to the token if necessary *************************************************/ if( PK11_Authenticate(slot, PR_TRUE /*loadcerts*/, NULL) != SECSuccess) { JSS_throwMsg(env, TOKEN_EXCEPTION, "unable to login to token"); goto finish; } /************************************************** * generate the key pair on the token *************************************************/ if( temporary ) { attrFlags |= PK11_ATTR_SESSION; } else { attrFlags |= PK11_ATTR_TOKEN; } if( extractable == 1 ) { attrFlags |= PK11_ATTR_EXTRACTABLE; } else if( extractable == 0 ) { attrFlags |= PK11_ATTR_UNEXTRACTABLE; } /* * The default of sensitive is set this way to be backward * compatible. */ if( sensitive == -1 ) { sensitive = !temporary; } /* * The PRIVATE/PUBLIC attributes are set this way to be backward * compatible with the original PK11_GenerateKeyPair call. */ if( sensitive ) { attrFlags |= (PK11_ATTR_SENSITIVE | PK11_ATTR_PRIVATE); } else { attrFlags |= (PK11_ATTR_INSENSITIVE | PK11_ATTR_PUBLIC); } *privk = PK11_GenerateKeyPairWithOpFlags(slot, mechanism, params, pubk, attrFlags, (CK_FLAGS) op_flags, (CK_FLAGS) op_flags_mask /* the ones we don't want*/, NULL /* default PW callback */ ); if( *privk == NULL ) { int errLength; char *errBuf; char *msgBuf; errLength = PR_GetErrorTextLength(); if(errLength > 0) { errBuf = PR_Malloc(errLength); if(errBuf == NULL) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } PR_GetErrorText(errBuf); } msgBuf = PR_smprintf("Keypair Generation failed on token with error: %d : %s", PR_GetError(), errLength>0? errBuf : ""); if(errLength>0) { PR_Free(errBuf); } JSS_throwMsg(env, TOKEN_EXCEPTION, msgBuf); PR_Free(msgBuf); goto finish; } return SECSuccess; finish: if(*privk!=NULL) { SECKEY_DestroyPrivateKey(*privk); *privk = NULL; } if(*pubk!=NULL) { SECKEY_DestroyPublicKey(*pubk); *pubk = NULL; } return SECFailure; } /* * make a common key gen function for both this file and PK11Token.c */ SECStatus JSS_PK11_generateKeyPair(JNIEnv *env, CK_MECHANISM_TYPE mechanism, PK11SlotInfo *slot, SECKEYPublicKey **pubk, SECKEYPrivateKey **privk, void *params, PRBool temporary, jint sensitive, jint extractable) { return JSS_PK11_generateKeyPairWithOpFlags(env, mechanism, slot, pubk, privk, params, temporary, sensitive, extractable, 0, 0); } /********************************************************************** * Local generic helpers */ static jobject PK11KeyPairGeneratorWithOpFlags(JNIEnv *env, jobject this, jobject token, CK_MECHANISM_TYPE mechanism, void *params, jboolean temporary, jint sensitive, jint extractable, jint op_flags, jint op_flags_mask) { PK11SlotInfo* slot; SECKEYPrivateKey *privk=NULL; SECKEYPublicKey *pubk=NULL; jobject keyPair=NULL; SECStatus rv; PR_ASSERT(env!=NULL && this!=NULL && token!=NULL); /************************************************** * get the slot pointer *************************************************/ if( JSS_PK11_getTokenSlotPtr(env, token, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } PR_ASSERT(slot != NULL); rv = JSS_PK11_generateKeyPairWithOpFlags(env, mechanism, slot, &pubk, &privk, params, temporary, sensitive, extractable, op_flags, op_flags_mask); if (rv != SECSuccess) { goto finish; } /************************************************** * wrap in a Java KeyPair object *************************************************/ keyPair = keysToKeyPair(env, &privk, &pubk); if(keyPair == NULL ) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } finish: if(privk!=NULL) { SECKEY_DestroyPrivateKey(privk); } if(pubk!=NULL) { SECKEY_DestroyPublicKey(pubk); } return keyPair; } static jobject PK11KeyPairGenerator(JNIEnv *env, jobject this, jobject token, CK_MECHANISM_TYPE mechanism, void *params, jboolean temporary, jint sensitive, jint extractable) { return PK11KeyPairGeneratorWithOpFlags(env, this, token, mechanism, params, temporary, sensitive, extractable, 0, 0); } /********************************************************************** * PK11KeyPairGenerator.generateRSAKeyPair */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11KeyPairGenerator_generateRSAKeyPair (JNIEnv *env, jobject this, jobject token, jint keySize, jlong publicExponent, jboolean temporary, jint sensitive, jint extractable) { PK11RSAGenParams params; PR_ASSERT(env!=NULL && this!=NULL && token!=NULL); /************************************************** * setup parameters *************************************************/ params.keySizeInBits = keySize; params.pe = publicExponent; return PK11KeyPairGenerator(env, this, token, CKM_RSA_PKCS_KEY_PAIR_GEN, ¶ms, temporary, sensitive, extractable); } /********************************************************************** * PK11KeyPairGenerator.generateRSAKeyPairWithOpFlags */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11KeyPairGenerator_generateRSAKeyPairWithOpFlags (JNIEnv *env, jobject this, jobject token, jint keySize, jlong publicExponent, jboolean temporary, jint sensitive, jint extractable, jint op_flags, jint op_flags_mask) { PK11RSAGenParams params; PR_ASSERT(env!=NULL && this!=NULL && token!=NULL); /************************************************** * setup parameters *************************************************/ params.keySizeInBits = keySize; params.pe = publicExponent; return PK11KeyPairGeneratorWithOpFlags(env, this, token, CKM_RSA_PKCS_KEY_PAIR_GEN, ¶ms, temporary, sensitive, extractable, op_flags, op_flags_mask); } #define ZERO_SECITEM(item) {(item).len=0; (item).data=NULL;} /********************************************************************** * * PK11KeyPairGenerator.generateDSAKeyPair * */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11KeyPairGenerator_generateDSAKeyPair (JNIEnv *env, jobject this, jobject token, jbyteArray P, jbyteArray Q, jbyteArray G, jboolean temporary, jint sensitive, jint extractable) { SECItem p, q, g; PQGParams *params=NULL; jobject keyPair=NULL; PR_ASSERT(env!=NULL && this!=NULL && token!=NULL && P!=NULL && Q!=NULL && G!=NULL); /* zero these so we can free them indiscriminately later */ ZERO_SECITEM(p); ZERO_SECITEM(q); ZERO_SECITEM(g); /************************************************** * Setup the parameters *************************************************/ if( JSS_ByteArrayToOctetString(env, P, &p) || JSS_ByteArrayToOctetString(env, Q, &q) || JSS_ByteArrayToOctetString(env, G, &g) ) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } params = PK11_PQG_NewParams(&p, &q, &g); if(params == NULL) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } keyPair = PK11KeyPairGenerator(env, this, token, CKM_DSA_KEY_PAIR_GEN, params, temporary, sensitive, extractable); finish: SECITEM_FreeItem(&p, PR_FALSE); SECITEM_FreeItem(&q, PR_FALSE); SECITEM_FreeItem(&g, PR_FALSE); PK11_PQG_DestroyParams(params); return keyPair; } /********************************************************************** * * PK11KeyPairGenerator.generateDSAKeyPair * */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11KeyPairGenerator_generateDSAKeyPairWithOpFlags (JNIEnv *env, jobject this, jobject token, jbyteArray P, jbyteArray Q, jbyteArray G, jboolean temporary, jint sensitive, jint extractable, jint op_flags, jint op_flags_mask) { SECItem p, q, g; PQGParams *params=NULL; jobject keyPair=NULL; PR_ASSERT(env!=NULL && this!=NULL && token!=NULL && P!=NULL && Q!=NULL && G!=NULL); /* zero these so we can free them indiscriminately later */ ZERO_SECITEM(p); ZERO_SECITEM(q); ZERO_SECITEM(g); /************************************************** * Setup the parameters *************************************************/ if( JSS_ByteArrayToOctetString(env, P, &p) || JSS_ByteArrayToOctetString(env, Q, &q) || JSS_ByteArrayToOctetString(env, G, &g) ) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } params = PK11_PQG_NewParams(&p, &q, &g); if(params == NULL) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } keyPair = PK11KeyPairGeneratorWithOpFlags(env, this, token, CKM_DSA_KEY_PAIR_GEN, params, temporary, sensitive, extractable, op_flags, op_flags_mask); finish: SECITEM_FreeItem(&p, PR_FALSE); SECITEM_FreeItem(&q, PR_FALSE); SECITEM_FreeItem(&g, PR_FALSE); PK11_PQG_DestroyParams(params); return keyPair; } void DumpItem(SECItem *item) { unsigned char *data = item->data; unsigned int i; for (i=0; i < item->len; i++) { printf(" %02x",data[i]); } printf(" : %8p %d\n", data, item->len); } /********************************************************************** * * PK11KeyPairGenerator.generateECKeyPair * */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11KeyPairGenerator_generateECKeyPair (JNIEnv *env, jobject this, jobject token, jbyteArray Curve, jboolean temporary, jint sensitive, jint extractable) { SECItem curve; jobject keyPair=NULL; PR_ASSERT(env!=NULL && this!=NULL && token!=NULL && Curve!=NULL ); /* zero these so we can free them indiscriminately later */ ZERO_SECITEM(curve); /************************************************** * Setup the parameters *************************************************/ if( JSS_ByteArrayToOctetString(env, Curve, &curve)) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } keyPair = PK11KeyPairGenerator(env, this, token, CKM_EC_KEY_PAIR_GEN, &curve, temporary, sensitive, extractable); finish: SECITEM_FreeItem(&curve, PR_FALSE); return keyPair; } /********************************************************************** * * PK11KeyPairGenerator.generateECKeyPairWithOpFlags * */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11KeyPairGenerator_generateECKeyPairWithOpFlags (JNIEnv *env, jobject this, jobject token, jbyteArray Curve, jboolean temporary, jint sensitive, jint extractable, jint op_flags, jint op_flags_mask) { SECItem curve; jobject keyPair=NULL; PR_ASSERT(env!=NULL && this!=NULL && token!=NULL && Curve!=NULL ); /* zero these so we can free them indiscriminately later */ ZERO_SECITEM(curve); /************************************************** * Setup the parameters *************************************************/ if( JSS_ByteArrayToOctetString(env, Curve, &curve)) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } keyPair = PK11KeyPairGeneratorWithOpFlags(env, this, token, CKM_EC_KEY_PAIR_GEN, &curve, temporary, sensitive, extractable, op_flags, op_flags_mask); finish: SECITEM_FreeItem(&curve, PR_FALSE); return keyPair; } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11KeyPairGenerator.java000066400000000000000000001434251412550063600255740ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import java.math.BigInteger; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidParameterException; import java.security.KeyPair; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.DSAParameterSpec; import java.security.spec.ECGenParameterSpec; import java.security.spec.RSAKeyGenParameterSpec; import java.util.Hashtable; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.crypto.KeyPairAlgorithm; import org.mozilla.jss.crypto.PQGParams; import org.mozilla.jss.crypto.Policy; import org.mozilla.jss.crypto.RSAParameterSpec; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.util.ECCurve; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A Key Pair Generator implemented using PKCS #11. * * @see org.mozilla.jss.crypto.PQGParams */ public final class PK11KeyPairGenerator extends org.mozilla.jss.crypto.KeyPairGeneratorSpi { public static Logger logger = LoggerFactory.getLogger(PK11KeyPairGenerator.class); // curve code for getting the actual EC curve private enum ECCurve_Code { // NIST, SEC2 Prime curves secp521r1 , // == nistp521 nistp521 , secp384r1 , // == nistp384 nistp384 , secp256r1 , // == nistp256 nistp256 , secp256k1 , secp224r1 , // == nistp224 nistp224 , secp224k1 , secp192r1 , // == nistp192 nistp192 , secp192k1 , secp160r2 , secp160r1 , secp160k1 , secp128r2 , secp128r1 , secp112r2 , secp112r1 , // NIST, SEC2 Binary curves sect571r1 , // == nistb571 nistb571 , sect571k1 , // == nistk571 nistk571 , sect409r1 , // == nistb409 nistb409 , sect409k1 , // == nistk409 nistk409 , sect283r1 , // == nistb283 nistb283 , sect283k1 , // == nistk283 nistk283 , sect239k1 , sect233r1 , // == nistb233 nistb233 , sect233k1 , // == nistk233 nistk233 , sect193r2 , sect193r1 , nistb163 , sect163r2 , // == nistb163 sect163r1 , sect163k1 , // == nistk163 nistk163 , sect131r2 , sect131r1 , sect113r2 , sect113r1 , // ANSI X9.62 Prime curves prime239v3 , prime239v2 , prime239v1 , prime192v3 , prime192v2 , prime192v1 , // == nistp192 // prime256v1 == nistp256 // ANSI X9.62 Binary curves c2pnb163v1 , c2pnb163v2 , c2pnb163v3 , c2pnb176v1 , c2tnb191v1 , c2tnb191v2 , c2tnb191v3 , //c2onb191v4 , //c2onb191v5 , c2pnb208w1 , c2tnb239v1 , c2tnb239v2 , c2tnb239v3 , //c2onb239v4 , //c2onb239v5 , c2pnb272w1 , c2pnb304w1 , c2tnb359v1 , c2pnb368w1 , c2tnb431r1 // no WTLS curves fo now }; private static Hashtable ECCurve_NameToCode = new Hashtable<>(); static { // NIST, SEC2 Prime curves ECCurve_NameToCode.put( "secp521r1", ECCurve_Code.secp521r1); ECCurve_NameToCode.put( "nistp521", ECCurve_Code.nistp521); ECCurve_NameToCode.put( "secp384r1", ECCurve_Code.secp384r1); ECCurve_NameToCode.put( "nistp384", ECCurve_Code.nistp384); ECCurve_NameToCode.put( "secp256r1", ECCurve_Code.secp256r1); ECCurve_NameToCode.put( "nistp256", ECCurve_Code.nistp256); ECCurve_NameToCode.put( "secp256k1", ECCurve_Code.secp256k1); ECCurve_NameToCode.put( "secp224r1", ECCurve_Code.secp224r1); ECCurve_NameToCode.put( "nistp224", ECCurve_Code.nistp224); ECCurve_NameToCode.put( "secp224k1", ECCurve_Code.secp224k1); ECCurve_NameToCode.put( "secp192r1", ECCurve_Code.secp192r1); ECCurve_NameToCode.put( "nistp192", ECCurve_Code.nistp192); ECCurve_NameToCode.put( "secp192k1", ECCurve_Code.secp192k1); ECCurve_NameToCode.put( "secp160r2", ECCurve_Code.secp160r2); ECCurve_NameToCode.put( "secp160r1", ECCurve_Code.secp160r1); ECCurve_NameToCode.put( "secp160k1", ECCurve_Code.secp160k1); ECCurve_NameToCode.put( "secp128r2", ECCurve_Code.secp128r2); ECCurve_NameToCode.put( "secp128r1", ECCurve_Code.secp128r1); ECCurve_NameToCode.put( "secp112r2", ECCurve_Code.secp112r2); ECCurve_NameToCode.put( "secp112r1", ECCurve_Code.secp112r1); // NIST, SEC2 Binary curves ECCurve_NameToCode.put( "sect571r1", ECCurve_Code.sect571r1); ECCurve_NameToCode.put( "nistb571", ECCurve_Code.nistb571); ECCurve_NameToCode.put( "sect571k1", ECCurve_Code.sect571k1); ECCurve_NameToCode.put( "nistk571", ECCurve_Code.nistk571); ECCurve_NameToCode.put( "sect409r1", ECCurve_Code.sect409r1); ECCurve_NameToCode.put( "nistb409", ECCurve_Code.nistb409); ECCurve_NameToCode.put( "sect409k1", ECCurve_Code.sect409k1); ECCurve_NameToCode.put( "nistk409", ECCurve_Code.nistk409); ECCurve_NameToCode.put( "sect283r1", ECCurve_Code.sect283r1); ECCurve_NameToCode.put( "nistb283", ECCurve_Code.nistb283); ECCurve_NameToCode.put( "sect283k1", ECCurve_Code.sect283k1); ECCurve_NameToCode.put( "nistk283", ECCurve_Code.nistk283); ECCurve_NameToCode.put( "sect239k1", ECCurve_Code.sect239k1); ECCurve_NameToCode.put( "sect233r1", ECCurve_Code.sect233r1); ECCurve_NameToCode.put( "nistb233", ECCurve_Code.nistb233); ECCurve_NameToCode.put( "sect233k1", ECCurve_Code.sect233k1); ECCurve_NameToCode.put( "nistk233", ECCurve_Code.nistk233); ECCurve_NameToCode.put( "sect193r2", ECCurve_Code.sect193r2); ECCurve_NameToCode.put( "sect193r1", ECCurve_Code.sect193r1); ECCurve_NameToCode.put( "nistb163", ECCurve_Code.nistb163); ECCurve_NameToCode.put( "sect163r2", ECCurve_Code.sect163r2); ECCurve_NameToCode.put( "sect163r1", ECCurve_Code.sect163r1); ECCurve_NameToCode.put( "sect163k1", ECCurve_Code.sect163k1); ECCurve_NameToCode.put( "nistk163", ECCurve_Code.nistk163); ECCurve_NameToCode.put( "sect131r2", ECCurve_Code.sect131r2); ECCurve_NameToCode.put( "sect131r1", ECCurve_Code.sect131r1); ECCurve_NameToCode.put( "sect113r2", ECCurve_Code.sect113r2); ECCurve_NameToCode.put( "sect113r1", ECCurve_Code.sect113r1); // ANSI Prime curves ECCurve_NameToCode.put( "prime239v3", ECCurve_Code.prime239v3); ECCurve_NameToCode.put( "prime239v2", ECCurve_Code.prime239v2); ECCurve_NameToCode.put( "prime239v1", ECCurve_Code.prime239v1); ECCurve_NameToCode.put( "prime192v3", ECCurve_Code.prime192v3); ECCurve_NameToCode.put( "prime192v2", ECCurve_Code.prime192v2); ECCurve_NameToCode.put( "prime192v1", ECCurve_Code.prime192v1); // ANSI Binary curves ECCurve_NameToCode.put( "c2pnb163v1", ECCurve_Code.c2pnb163v1); ECCurve_NameToCode.put( "c2pnb163v2", ECCurve_Code.c2pnb163v2); ECCurve_NameToCode.put( "c2pnb163v3", ECCurve_Code.c2pnb163v3); ECCurve_NameToCode.put( "c2pnb176v1", ECCurve_Code.c2pnb176v1); ECCurve_NameToCode.put( "c2tnb191v1", ECCurve_Code.c2tnb191v1); ECCurve_NameToCode.put( "c2tnb191v2", ECCurve_Code.c2tnb191v2); ECCurve_NameToCode.put( "c2tnb191v3", ECCurve_Code.c2tnb191v3); //ECCurve_NameToCode.put( // "c2onb191v4", ECCurve_Code.c2onb191v4); //ECCurve_NameToCode.put( // "c2onb191v5", ECCurve_Code.c2onb191v5); ECCurve_NameToCode.put( "c2pnb208w1", ECCurve_Code.c2pnb208w1); ECCurve_NameToCode.put( "c2tnb239v1", ECCurve_Code.c2tnb239v1); ECCurve_NameToCode.put( "c2tnb239v2", ECCurve_Code.c2tnb239v2); ECCurve_NameToCode.put( "c2tnb239v3", ECCurve_Code.c2tnb239v3); //ECCurve_NameToCode.put( // "c2onb239v4", ECCurve_Code.c2onb239v4); //ECCurve_NameToCode.put( // "c2onb239v5", ECCurve_Code.c2onb239v5); ECCurve_NameToCode.put( "c2pnb272w1", ECCurve_Code.c2pnb272w1); ECCurve_NameToCode.put( "c2pnb304w1", ECCurve_Code.c2pnb304w1); ECCurve_NameToCode.put( "c2tnb359v1", ECCurve_Code.c2tnb359v1); ECCurve_NameToCode.put( "c2pnb368w1", ECCurve_Code.c2pnb368w1); ECCurve_NameToCode.put( "c2tnb431r1", ECCurve_Code.c2tnb431r1); } // The crypto operations the key will support. It is the logical OR // of the opFlag constants, each specifying a supported operation. private long opFlags = 0; private long opFlagsMask = 0; /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// /** * Constructor for PK11KeyPairGenerator. * @param token The PKCS #11 token that the keypair will be generated on. * @param algorithm The type of key that will be generated. Currently, * KeyPairAlgorithm.RSA , * KeyPairAlgorithm.DSA and * KeyPairAlgorithm.EC are supported. * @throws NoSuchAlgorithmException * @throws TokenException */ public PK11KeyPairGenerator(PK11Token token, KeyPairAlgorithm algorithm) throws NoSuchAlgorithmException, TokenException { assert(token!=null && algorithm!=null); mKeygenOnInternalToken = false; // Make sure we can do this kind of keygen if( ! token.doesAlgorithm(algorithm) ) { if( token.doesAlgorithm( algorithm.getAlgFamily() ) && token.isWritable() ) { // NSS will do the keygen on the internal module // and move the key to the token. We'll say this is // OK for now. mKeygenOnInternalToken = true; } else { throw new NoSuchAlgorithmException(); } } this.token = token; this.algorithm = algorithm; } /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Public Methods /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// /** * Initializes this KeyPairGenerator with the given key strength. * *

For DSA key generation, pre-cooked PQG values will be used * be used if the key size is 512, 768, or 1024. Otherwise, an * InvalidParameterException will be thrown. * * @param strength The strength (size) of the keys that will be generated. * @param random Ignored * @exception InvalidParameterException If the key strength is not * supported by the algorithm or this implementation. */ @Override public void initialize(int strength, SecureRandom random) throws InvalidParameterException { if(algorithm == KeyPairAlgorithm.RSA) { params = new RSAParameterSpec(strength, DEFAULT_RSA_PUBLIC_EXPONENT); } else if(algorithm == KeyPairAlgorithm.DSA) { if(strength==512) { params = PQG512; } else if(strength==768) { params = PQG768; } else if(strength==1024) { params = PQG1024; } else { throw new InvalidParameterException( "In order to use pre-cooked PQG values, key strength must"+ "be 512, 768, or 1024."); } } else { assert( algorithm == KeyPairAlgorithm.EC ); if (strength < 112) { // for EC, "strength" is actually a code for curves defined in // ECCurve_Code params = getECCurve(strength); } else { // this is the old method of strength to curve mapping, // which is somewhat defective params = getCurve(strength); } } } /** * Initializes this KeyPairGenerator with the given algorithm-specific * parameters. * * @param params The algorithm-specific parameters that will govern * key pair generation. * @param random Ignored * @throws InvalidAlgorithmParameterException If the parameters * are inappropriate for the key type or are not supported by * this implementation. */ @Override public void initialize(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { if(params == null) { throw new InvalidAlgorithmParameterException("Null parameters"); } if(algorithm == KeyPairAlgorithm.RSA) { if (!(params instanceof RSAKeyGenParameterSpec)) { throw new InvalidAlgorithmParameterException(); } // Security library stores public exponent in an unsigned long if (((RSAKeyGenParameterSpec)params).getPublicExponent().bitLength() > 31) { throw new InvalidAlgorithmParameterException( "RSA Public Exponent must fit in 31 or fewer bits."); } } else if ( algorithm == KeyPairAlgorithm.DSA ){ if(! (params instanceof DSAParameterSpec) ) { throw new InvalidAlgorithmParameterException(); } } else { assert(algorithm == KeyPairAlgorithm.EC); if (params instanceof ECGenParameterSpec) { ECGenParameterSpec standard_params = (ECGenParameterSpec)params; String curve_name = standard_params.getName(); ECCurve curve = ECCurve.fromName(curve_name); if (curve == null) { throw new InvalidAlgorithmParameterException("Unable to find curve with the given name: " + curve_name); } OBJECT_IDENTIFIER[] oid = curve.getOIDs(); assert(oid.length >= 1); byte[] encoded_oid = ASN1Util.encode(oid[0]); params = new PK11ParameterSpec(encoded_oid); } if (!(params instanceof PK11ParameterSpec)) { throw new InvalidAlgorithmParameterException("Expected params to either be an instance of ECGenParameterSpec or PK11ParameterSpec!"); } } // future add support for X509EncodedSpec this.params = params; } /** * Generates a key pair on a token. Uses parameters if they were passed * in through a call to initialize, otherwise uses defaults. * @return * @throws TokenException */ @Override public KeyPair generateKeyPair() throws TokenException { if(algorithm == KeyPairAlgorithm.RSA) { if(params != null) { RSAKeyGenParameterSpec rsaparams = (RSAKeyGenParameterSpec)params; if (rsaparams.getKeysize() < Policy.RSA_MINIMUM_KEY_SIZE) { String msg = "unsafe RSA key size of "; msg += rsaparams.getKeysize() + ". Policy.RSA_MINIMUM_KEY_SIZE "; msg += "dictates a minimum of " + Policy.RSA_MINIMUM_KEY_SIZE; if (Policy.ENFORCING_KEY_SIZES) { throw new TokenException("Disallowing " + msg); } else { logger.warn("Ignored jss.crypto.Policy violation: " + msg); } } if (rsaparams.getPublicExponent().longValue() < Policy.RSA_MINIMUM_PUBLIC_EXPONENT.longValue()) { String msg = "unsafe RSA exponent of "; msg += rsaparams.getPublicExponent().longValue() + ". "; msg += "Policy.RSA_MINIMUM_PUBLIC_EXPONENT dictates a minimum of "; msg += Policy.RSA_MINIMUM_PUBLIC_EXPONENT.longValue(); if (Policy.ENFORCING_KEY_SIZES) { throw new TokenException("Disallowing " + msg); } else { logger.warn("Ignored jss.crypto.Policy violation: " + msg); } } return generateRSAKeyPairWithOpFlags( token, rsaparams.getKeysize(), rsaparams.getPublicExponent().longValue(), temporaryPairMode, sensitivePairMode, extractablePairMode, (int) opFlags, (int) opFlagsMask); } else { return generateRSAKeyPairWithOpFlags( token, DEFAULT_RSA_KEY_SIZE, DEFAULT_RSA_PUBLIC_EXPONENT.longValue(), temporaryPairMode, sensitivePairMode, extractablePairMode, (int) opFlags, (int) opFlagsMask); } } else if(algorithm == KeyPairAlgorithm.DSA ) { if(params==null) { params = PQG1024; } DSAParameterSpec dsaParams = (DSAParameterSpec)params; return generateDSAKeyPairWithOpFlags( token, PQGParams.BigIntegerToUnsignedByteArray(dsaParams.getP()), PQGParams.BigIntegerToUnsignedByteArray(dsaParams.getQ()), PQGParams.BigIntegerToUnsignedByteArray(dsaParams.getG()), temporaryPairMode, sensitivePairMode, extractablePairMode, (int) opFlags, (int) opFlagsMask); } else { assert( algorithm == KeyPairAlgorithm.EC ); // requires JAVA 1.5 for ECParameters. // //AlgorithmParameters ecParams = // AlgorithmParameters.getInstance("ECParameters"); // ecParams.init(params); PK11ParameterSpec ecParams = (PK11ParameterSpec) params; return generateECKeyPairWithOpFlags( token, ecParams.getEncoded(), /* curve */ temporaryPairMode, sensitivePairMode, extractablePairMode, (int) opFlags, (int) opFlagsMask); } } /** * @return true if the keypair generation will be done on the * internal token and then moved to this token. */ @Override public boolean keygenOnInternalToken() { return mKeygenOnInternalToken; } /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Native Implementation Methods /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// /** * Generates an RSA key pair with the given size and public exponent. */ private native KeyPair generateRSAKeyPair(PK11Token token, int keySize, long publicExponent, boolean temporary, int sensitive, int extractable) throws TokenException; /** * Generates an RSA key pair with the given size and public exponent. * Adds the ability to specify a set of flags and masks * to control how NSS generates the key pair. */ private native KeyPair generateRSAKeyPairWithOpFlags(PK11Token token, int keySize, long publicExponent, boolean temporary, int sensitive, int extractable, int op_flags, int op_flags_mask) throws TokenException; /** * Generates a DSA key pair with the given P, Q, and G values. * P, Q, and G are stored as big-endian twos-complement octet strings. */ private native KeyPair generateDSAKeyPair(PK11Token token, byte[] P, byte[] Q, byte[] G, boolean temporary, int sensitive, int extractable) throws TokenException; /** * Generates a DSA key pair with the given P, Q, and G values. * P, Q, and G are stored as big-endian twos-complement octet strings. * Adds the ability to specify a set of flags and masks * to control how NSS generates the key pair. */ private native KeyPair generateDSAKeyPairWithOpFlags(PK11Token token, byte[] P, byte[] Q, byte[] G, boolean temporary, int sensitive, int extractable, int op_flags, int op_flags_mask) throws TokenException; /** * Generates a EC key pair with the given a curve. * Curves are stored as DER Encoded Parameters. */ private native KeyPair generateECKeyPair(PK11Token token, byte[] Curve, boolean temporary, int sensitive, int extractable) throws TokenException; /** * Generates a EC key pair with the given a curve. * Curves are stored as DER Encoded Parameters. * Adds the ability to specify a set of flags and masks * to control how NSS generates the key pair. */ private native KeyPair generateECKeyPairWithOpFlags(PK11Token token, byte[] Curve, boolean temporary, int sensitive, int extractable, int op_flags, int op_flags_mask) throws TokenException; /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Defaults /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// private static final int DEFAULT_RSA_KEY_SIZE = 2048; private static final BigInteger DEFAULT_RSA_PUBLIC_EXPONENT = BigInteger.valueOf(65537); ////////////////////////////////////////////////////////////////////// // 1024-bit PQG parameters // These were generated and verified using the // org.mozilla.jss.crypto.PQGParams class. ////////////////////////////////////////////////////////////////////// private static final String p1024= "135839652435190934085800139191680301864221874900900696919010316554114342871389066526982023513828891845682496590926522957486592076092819515303251959435284578074745022943475516750500021440278782993316814165831392449756706958779266394680687474113495272524355075654433600922751920548192539119568200162784715902571"; private static final String q1024= "1289225024022202541601051225376429063716419728261"; private static final String g1024= "9365079229044517973775853147905914670746128595481021901304748201231245287028018351117994470223961367498481071639148009750748608477086914440940765659773400233006204556380834403997210445996745757996115285802608489502160956380238739417382954486304730446079375880915926936667959108637040861595671319957190194969"; private static final String h1024= "52442921523337940900621893014039829709890959980326720828933601226740749524581606283131306291278616835323956710592993182613544059214633911716533418368425327413628234095671352084418677611348898811691107611640282098605730539089258655659910952545940615065321018163879856499128636989240131903260975031351698627473"; private static final String seed1024= "99294487279227522120410987308721952265545668206337642687581596155167227884587528576179879564731162765515189527566190299324927751299864501359105446993895763527646668003992063667962831489586752303126546478655915858883436326503676798267446073013163508014466163441488290854738816489359449082537210762470653355837"; private static final int counter1024 = 159; /** * Pre-cooked PQG values for 1024-bit keypairs, along with the seed, * counter, and H values needed to verify them. */ public static final PQGParams PQG1024 = new PQGParams( new BigInteger(p1024), new BigInteger(q1024), new BigInteger(g1024), new BigInteger(seed1024), counter1024, new BigInteger(h1024)); ////////////////////////////////////////////////////////////////////// // 768-bit PQG parameters // These were generated and verified using the // org.mozilla.jss.crypto.PQGParams class. ////////////////////////////////////////////////////////////////////// private static final String p768 = "1334591549939035619289567230283054603122655003980178118026955029363553392594293499178687789871628588392413078786977899109276604404053531960657701920766542891720144660923735290663050045086516783083489369477138289683344192203747015183"; private static final String q768 = "1356132865877303155992130272917916166541739006871"; private static final String g768 = "1024617924160404238802957719732914916383807485923819254303813897112921288261546213295904612554364830820266594592843780972915270096284099079324418834215265083315386166747220804977600828688227714319518802565604893756612386174125343163"; private static final String seed768 = "818335465751997015393064637168438154352349887221925302425470688493624428407506863871577128315308555744979456856342994235252156194662586703244255741598129996211081771019031721876068721218509213355334043303099174315838637885951947797"; private static final int counter768 = 80; private static final String h768 = "640382699969409389484886950168366372251172224987648937408021020040753785108834000620831523080773231719549705102680417704245010958792653770817759388668805215557594892534053348624875390588773257372677159854630106242075665177245698591"; /** * Pre-cooked PQG values for 768-bit keypairs, along with the seed, * counter, and H values needed to verify them. */ public static final PQGParams PQG768 = new PQGParams( new BigInteger(p768), new BigInteger(q768), new BigInteger(g768), new BigInteger(seed768), counter768, new BigInteger(h768)); ////////////////////////////////////////////////////////////////////// // 512-bit PQG parameters // These were generated and verified using the // org.mozilla.jss.crypto.PQGParams class. ////////////////////////////////////////////////////////////////////// private static final String p512 = "6966483207285155416780416172202915863379050665227482416115451434656043093992853756903066653962454938528584622842487778598918381346739078775480034378802841"; private static final String q512 = "1310301134281640075932276656367326462518739803527"; private static final String g512 = "1765808308320938820731237312304158486199455718816858489736043318496656574508696475222741642343469219895005992985361010111736160340009944528784078083324884"; private static final String h512 = "1166033533097555931825481846268490827226947692615252570752313574243187654088977281409544725210974913958636100321681636002587474728477655589742540645702652"; private static final String seed512 = "1823071686803672528716836609217295942310764795778335243232708299998660956064222751939859670873282519585591423918449571513004815205037154878988595168291600"; private static final int counter512 = 186; /** * Pre-cooked PQG values for 512-bit keypairs, along with the seed, * counter, and H values needed to verify them. */ public static final PQGParams PQG512 = new PQGParams( new BigInteger(p512), new BigInteger(q512), new BigInteger(g512), new BigInteger(seed512), counter512, new BigInteger(h512)); /////////////////////////////////////////////////////////////////////// // Test the PQG parameters /////////////////////////////////////////////////////////////////////// private static boolean defaultsTested = false; private static synchronized void testDefaults() { if(!defaultsTested) { assert(PQG1024.paramsAreValid()); assert(PQG768.paramsAreValid()); assert(PQG512.paramsAreValid()); defaultsTested = true; } } @Override public void temporaryPairs(boolean temp) { temporaryPairMode = temp; } @Override public void sensitivePairs(boolean sensitive) { sensitivePairMode = sensitive ? 1 : 0; } @Override public void extractablePairs(boolean extractable) { extractablePairMode = extractable ? 1 : 0; } /** * Sets the requested key usages desired for the * generated key pair. * This allows the caller to suggest how NSS generates the key pair. * @param usages List of desired key usages. * @param usages_mask Corresponding mask for the key usages. * if a usages is desired, make sure it is in the mask as well. */ @Override public void setKeyPairUsages(org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage[] usages, org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage[] usages_mask) { this.opFlags = 0; this.opFlagsMask = 0; if(usages != null) { for( int i = 0; i < usages.length; i++ ) { if( usages[i] != null ) { this.opFlags |= usages[i].value(); } } } if(usages_mask != null) { for( int i = 0; i < usages_mask.length; i++ ) { if( usages_mask[i] != null ) { this.opFlagsMask |= usages_mask[i].value(); } } } } // // requires JAVA 1.5 // //private AlgorithmParameterSpec getCurve(int strength) { //} private static final OBJECT_IDENTIFIER ANSI_X962_PRIME_CURVE = new OBJECT_IDENTIFIER( new long[] { 1, 2, 840, 10045, 3, 1 } ); private static final OBJECT_IDENTIFIER ANSI_X962_BINARY_CURVE = new OBJECT_IDENTIFIER( new long[] { 1, 2, 840, 10045, 3, 0 } ); private static final OBJECT_IDENTIFIER SECG_EC_CURVE = new OBJECT_IDENTIFIER( new long[] { 1, 3, 132, 0 } ); // ANSI Prime curves static final OBJECT_IDENTIFIER CURVE_ANSI_P192V1 = ANSI_X962_PRIME_CURVE.subBranch(1); static final OBJECT_IDENTIFIER CURVE_ANSI_P192V2 = ANSI_X962_PRIME_CURVE.subBranch(2); static final OBJECT_IDENTIFIER CURVE_ANSI_P192V3 = ANSI_X962_PRIME_CURVE.subBranch(3); static final OBJECT_IDENTIFIER CURVE_ANSI_P239V1 = ANSI_X962_PRIME_CURVE.subBranch(4); static final OBJECT_IDENTIFIER CURVE_ANSI_P239V2 = ANSI_X962_PRIME_CURVE.subBranch(5); static final OBJECT_IDENTIFIER CURVE_ANSI_P239V3 = ANSI_X962_PRIME_CURVE.subBranch(6); static final OBJECT_IDENTIFIER CURVE_ANSI_P256V1 = ANSI_X962_PRIME_CURVE.subBranch(7); // ANSI Binary curves static final OBJECT_IDENTIFIER CURVE_ANSI_PNB163V1 =ANSI_X962_BINARY_CURVE.subBranch(1); static final OBJECT_IDENTIFIER CURVE_ANSI_PNB163V2 =ANSI_X962_BINARY_CURVE.subBranch(2); static final OBJECT_IDENTIFIER CURVE_ANSI_PNB163V3 =ANSI_X962_BINARY_CURVE.subBranch(3); static final OBJECT_IDENTIFIER CURVE_ANSI_PNB176V1 =ANSI_X962_BINARY_CURVE.subBranch(4); static final OBJECT_IDENTIFIER CURVE_ANSI_TNB191V1 =ANSI_X962_BINARY_CURVE.subBranch(5); static final OBJECT_IDENTIFIER CURVE_ANSI_TNB191V2 =ANSI_X962_BINARY_CURVE.subBranch(6); static final OBJECT_IDENTIFIER CURVE_ANSI_TNB191V3 =ANSI_X962_BINARY_CURVE.subBranch(7); static final OBJECT_IDENTIFIER CURVE_ANSI_ONB191V4 =ANSI_X962_BINARY_CURVE.subBranch(8); static final OBJECT_IDENTIFIER CURVE_ANSI_ONB191V5 =ANSI_X962_BINARY_CURVE.subBranch(9); static final OBJECT_IDENTIFIER CURVE_ANSI_PNB208W1 =ANSI_X962_BINARY_CURVE.subBranch(10); static final OBJECT_IDENTIFIER CURVE_ANSI_TNB239V1 =ANSI_X962_BINARY_CURVE.subBranch(11); static final OBJECT_IDENTIFIER CURVE_ANSI_TNB239V2 =ANSI_X962_BINARY_CURVE.subBranch(12); static final OBJECT_IDENTIFIER CURVE_ANSI_TNB239V3 =ANSI_X962_BINARY_CURVE.subBranch(13); static final OBJECT_IDENTIFIER CURVE_ANSI_ONB239V4 =ANSI_X962_BINARY_CURVE.subBranch(14); static final OBJECT_IDENTIFIER CURVE_ANSI_ONB239V5 =ANSI_X962_BINARY_CURVE.subBranch(15); static final OBJECT_IDENTIFIER CURVE_ANSI_PNB272W1 =ANSI_X962_BINARY_CURVE.subBranch(16); static final OBJECT_IDENTIFIER CURVE_ANSI_PNB304W1 =ANSI_X962_BINARY_CURVE.subBranch(17); static final OBJECT_IDENTIFIER CURVE_ANSI_TNB359V1 =ANSI_X962_BINARY_CURVE.subBranch(18); static final OBJECT_IDENTIFIER CURVE_ANSI_PNB368W1 =ANSI_X962_BINARY_CURVE.subBranch(19); static final OBJECT_IDENTIFIER CURVE_ANSI_TNB431R1 =ANSI_X962_BINARY_CURVE.subBranch(20); // SEG Prime curves static final OBJECT_IDENTIFIER CURVE_SECG_P112R1 = SECG_EC_CURVE.subBranch(6); static final OBJECT_IDENTIFIER CURVE_SECG_P112R2 = SECG_EC_CURVE.subBranch(7); static final OBJECT_IDENTIFIER CURVE_SECG_P128R1 = SECG_EC_CURVE.subBranch(28); static final OBJECT_IDENTIFIER CURVE_SECG_P128R2 = SECG_EC_CURVE.subBranch(29); static final OBJECT_IDENTIFIER CURVE_SECG_P160K1 = SECG_EC_CURVE.subBranch(9); static final OBJECT_IDENTIFIER CURVE_SECG_P160R1 = SECG_EC_CURVE.subBranch(8); static final OBJECT_IDENTIFIER CURVE_SECG_P160R2 = SECG_EC_CURVE.subBranch(30); static final OBJECT_IDENTIFIER CURVE_SECG_P192K1 = SECG_EC_CURVE.subBranch(31); static final OBJECT_IDENTIFIER CURVE_SECG_P224K1 = SECG_EC_CURVE.subBranch(32); static final OBJECT_IDENTIFIER CURVE_SECG_P224R1 = SECG_EC_CURVE.subBranch(33); static final OBJECT_IDENTIFIER CURVE_SECG_P256K1 = SECG_EC_CURVE.subBranch(10); static final OBJECT_IDENTIFIER CURVE_SECG_P384R1 = SECG_EC_CURVE.subBranch(34); static final OBJECT_IDENTIFIER CURVE_SECG_P521R1 = SECG_EC_CURVE.subBranch(35); // SEG Binary curves static final OBJECT_IDENTIFIER CURVE_SECG_T113R1 = SECG_EC_CURVE.subBranch(4); static final OBJECT_IDENTIFIER CURVE_SECG_T113R2 = SECG_EC_CURVE.subBranch(5); static final OBJECT_IDENTIFIER CURVE_SECG_T131R1 = SECG_EC_CURVE.subBranch(22); static final OBJECT_IDENTIFIER CURVE_SECG_T131R2 = SECG_EC_CURVE.subBranch(23); static final OBJECT_IDENTIFIER CURVE_SECG_T163K1 = SECG_EC_CURVE.subBranch(1); static final OBJECT_IDENTIFIER CURVE_SECG_T163R1 = SECG_EC_CURVE.subBranch(2); static final OBJECT_IDENTIFIER CURVE_SECG_T163R2 = SECG_EC_CURVE.subBranch(15); static final OBJECT_IDENTIFIER CURVE_SECG_T193R1 = SECG_EC_CURVE.subBranch(24); static final OBJECT_IDENTIFIER CURVE_SECG_T193R2 = SECG_EC_CURVE.subBranch(25); static final OBJECT_IDENTIFIER CURVE_SECG_T233K1 = SECG_EC_CURVE.subBranch(26); static final OBJECT_IDENTIFIER CURVE_SECG_T233R1 = SECG_EC_CURVE.subBranch(27); static final OBJECT_IDENTIFIER CURVE_SECG_T239K1 = SECG_EC_CURVE.subBranch(3); static final OBJECT_IDENTIFIER CURVE_SECG_T283K1 = SECG_EC_CURVE.subBranch(16); static final OBJECT_IDENTIFIER CURVE_SECG_T283R1 = SECG_EC_CURVE.subBranch(17); static final OBJECT_IDENTIFIER CURVE_SECG_T409K1 = SECG_EC_CURVE.subBranch(36); static final OBJECT_IDENTIFIER CURVE_SECG_T409R1 = SECG_EC_CURVE.subBranch(37); static final OBJECT_IDENTIFIER CURVE_SECG_T571K1 = SECG_EC_CURVE.subBranch(38); static final OBJECT_IDENTIFIER CURVE_SECG_T571R1 = SECG_EC_CURVE.subBranch(39); // the EC curvecode to oid hash table private static Hashtable mECCurve_CodeToCurve = new Hashtable<>(); static { // SEG Prime curves mECCurve_CodeToCurve.put( ECCurve_Code.secp521r1.ordinal(), CURVE_SECG_P521R1); mECCurve_CodeToCurve.put( ECCurve_Code.nistp521.ordinal(), CURVE_SECG_P521R1); mECCurve_CodeToCurve.put( ECCurve_Code.secp384r1.ordinal(), CURVE_SECG_P384R1); mECCurve_CodeToCurve.put( ECCurve_Code.nistp384.ordinal(), CURVE_SECG_P384R1); mECCurve_CodeToCurve.put( ECCurve_Code.secp256r1.ordinal(), CURVE_ANSI_P256V1); mECCurve_CodeToCurve.put( ECCurve_Code.nistp256.ordinal(), CURVE_ANSI_P256V1); mECCurve_CodeToCurve.put( ECCurve_Code.secp256k1.ordinal(), CURVE_SECG_P256K1); mECCurve_CodeToCurve.put( ECCurve_Code.secp224r1.ordinal(), CURVE_SECG_P224R1); mECCurve_CodeToCurve.put( ECCurve_Code.nistp224.ordinal(), CURVE_SECG_P224R1); mECCurve_CodeToCurve.put( ECCurve_Code.secp224k1.ordinal(), CURVE_SECG_P224K1); mECCurve_CodeToCurve.put( ECCurve_Code.secp192r1.ordinal(), CURVE_ANSI_P192V1); mECCurve_CodeToCurve.put( ECCurve_Code.nistp192.ordinal(), CURVE_ANSI_P192V1); mECCurve_CodeToCurve.put( ECCurve_Code.secp192k1.ordinal(), CURVE_SECG_P192K1); mECCurve_CodeToCurve.put( ECCurve_Code.secp160r2.ordinal(), CURVE_SECG_P160R2); mECCurve_CodeToCurve.put( ECCurve_Code.secp160r1.ordinal(), CURVE_SECG_P160R1); mECCurve_CodeToCurve.put( ECCurve_Code.secp160k1.ordinal(), CURVE_SECG_P160K1); mECCurve_CodeToCurve.put( ECCurve_Code.secp128r2.ordinal(), CURVE_SECG_P128R2); mECCurve_CodeToCurve.put( ECCurve_Code.secp128r1.ordinal(), CURVE_SECG_P128R1); mECCurve_CodeToCurve.put( ECCurve_Code.secp112r2.ordinal(), CURVE_SECG_P112R2); mECCurve_CodeToCurve.put( ECCurve_Code.secp112r1.ordinal(), CURVE_SECG_P112R1); // SEG Binary curves mECCurve_CodeToCurve.put( ECCurve_Code.sect571r1.ordinal(), CURVE_SECG_T571R1); mECCurve_CodeToCurve.put( ECCurve_Code.nistb571.ordinal(), CURVE_SECG_T571R1); mECCurve_CodeToCurve.put( ECCurve_Code.sect571k1.ordinal(), CURVE_SECG_T571K1); mECCurve_CodeToCurve.put( ECCurve_Code.nistk571.ordinal(), CURVE_SECG_T571K1); mECCurve_CodeToCurve.put( ECCurve_Code.sect409r1.ordinal(), CURVE_SECG_T409R1); mECCurve_CodeToCurve.put( ECCurve_Code.nistb409.ordinal(), CURVE_SECG_T409R1); mECCurve_CodeToCurve.put( ECCurve_Code.sect409k1.ordinal(), CURVE_SECG_T409K1); mECCurve_CodeToCurve.put( ECCurve_Code.nistk409.ordinal(), CURVE_SECG_T409K1); mECCurve_CodeToCurve.put( ECCurve_Code.sect283r1.ordinal(), CURVE_SECG_T283R1); mECCurve_CodeToCurve.put( ECCurve_Code.nistb283.ordinal(), CURVE_SECG_T283R1); mECCurve_CodeToCurve.put( ECCurve_Code.sect283k1.ordinal(), CURVE_SECG_T283K1); mECCurve_CodeToCurve.put( ECCurve_Code.nistk283.ordinal(), CURVE_SECG_T283K1); mECCurve_CodeToCurve.put( ECCurve_Code.sect239k1.ordinal(), CURVE_SECG_T239K1); mECCurve_CodeToCurve.put( ECCurve_Code.sect233r1.ordinal(), CURVE_SECG_T233R1); mECCurve_CodeToCurve.put( ECCurve_Code.nistb233.ordinal(), CURVE_SECG_T233R1); mECCurve_CodeToCurve.put( ECCurve_Code.sect233k1.ordinal(), CURVE_SECG_T233K1); mECCurve_CodeToCurve.put( ECCurve_Code.nistk233.ordinal(), CURVE_SECG_T233K1); mECCurve_CodeToCurve.put( ECCurve_Code.sect193r2.ordinal(), CURVE_SECG_T193R2); mECCurve_CodeToCurve.put( ECCurve_Code.sect193r1.ordinal(), CURVE_SECG_T193R1); mECCurve_CodeToCurve.put( ECCurve_Code.nistb163.ordinal(), CURVE_SECG_T163K1); mECCurve_CodeToCurve.put( ECCurve_Code.sect163r2.ordinal(), CURVE_SECG_T163R2); mECCurve_CodeToCurve.put( ECCurve_Code.sect163r1.ordinal(), CURVE_SECG_T163R1); mECCurve_CodeToCurve.put( ECCurve_Code.sect163k1.ordinal(), CURVE_SECG_T163K1); mECCurve_CodeToCurve.put( ECCurve_Code.nistk163.ordinal(), CURVE_SECG_T163K1); mECCurve_CodeToCurve.put( ECCurve_Code.sect131r2.ordinal(), CURVE_SECG_T131R2); mECCurve_CodeToCurve.put( ECCurve_Code.sect131r1.ordinal(), CURVE_SECG_T131R1); mECCurve_CodeToCurve.put( ECCurve_Code.sect113r2.ordinal(), CURVE_SECG_T113R2); mECCurve_CodeToCurve.put( ECCurve_Code.sect113r1.ordinal(), CURVE_SECG_T113R1); // ANSI Prime curves mECCurve_CodeToCurve.put( ECCurve_Code.prime239v3.ordinal(), CURVE_ANSI_P239V3); mECCurve_CodeToCurve.put( ECCurve_Code.prime239v2.ordinal(), CURVE_ANSI_P239V2); mECCurve_CodeToCurve.put( ECCurve_Code.prime239v1.ordinal(), CURVE_ANSI_P239V1); mECCurve_CodeToCurve.put( ECCurve_Code.prime192v3.ordinal(), CURVE_ANSI_P192V3); mECCurve_CodeToCurve.put( ECCurve_Code.prime192v2.ordinal(), CURVE_ANSI_P192V2); mECCurve_CodeToCurve.put( ECCurve_Code.prime192v1.ordinal(), CURVE_ANSI_P192V1); // ANSI Binary curves mECCurve_CodeToCurve.put( ECCurve_Code.c2pnb163v1.ordinal(), CURVE_ANSI_PNB163V1); mECCurve_CodeToCurve.put( ECCurve_Code.c2pnb163v2.ordinal(), CURVE_ANSI_PNB163V2); mECCurve_CodeToCurve.put( ECCurve_Code.c2pnb163v3.ordinal(), CURVE_ANSI_PNB163V3); mECCurve_CodeToCurve.put( ECCurve_Code.c2pnb176v1.ordinal(), CURVE_ANSI_PNB176V1); mECCurve_CodeToCurve.put( ECCurve_Code.c2tnb191v1.ordinal(), CURVE_ANSI_TNB191V1); mECCurve_CodeToCurve.put( ECCurve_Code.c2tnb191v2.ordinal(), CURVE_ANSI_TNB191V2); mECCurve_CodeToCurve.put( ECCurve_Code.c2tnb191v3.ordinal(), CURVE_ANSI_TNB191V3); //mECCurve_CodeToCurve.put( // ECCurve_Code.c2onb191v4.ordinal(), (Object) CURVE_ANSI_ONB191V4); //mECCurve_CodeToCurve.put( // ECCurve_Code.c2onb191v5.ordinal(), (Object) CURVE_ANSI_ONB191V5); mECCurve_CodeToCurve.put( ECCurve_Code.c2pnb208w1.ordinal(), CURVE_ANSI_PNB208W1); mECCurve_CodeToCurve.put( ECCurve_Code.c2tnb239v1.ordinal(), CURVE_ANSI_TNB239V1); mECCurve_CodeToCurve.put( ECCurve_Code.c2tnb239v2.ordinal(), CURVE_ANSI_TNB239V2); mECCurve_CodeToCurve.put( ECCurve_Code.c2tnb239v3.ordinal(), CURVE_ANSI_TNB239V3); //mECCurve_CodeToCurve.put( // ECCurve_Code.c2onb239v4.ordinal(), (Object) CURVE_ANSI_ONB239V4); //mECCurve_CodeToCurve.put( // ECCurve_Code.c2onb239v5.ordinal(), (Object) CURVE_ANSI_ONB239V5); mECCurve_CodeToCurve.put( ECCurve_Code.c2pnb272w1.ordinal(), CURVE_ANSI_PNB272W1); mECCurve_CodeToCurve.put( ECCurve_Code.c2pnb304w1.ordinal(), CURVE_ANSI_PNB304W1); mECCurve_CodeToCurve.put( ECCurve_Code.c2tnb359v1.ordinal(), CURVE_ANSI_TNB359V1); mECCurve_CodeToCurve.put( ECCurve_Code.c2pnb368w1.ordinal(), CURVE_ANSI_PNB368W1); mECCurve_CodeToCurve.put( ECCurve_Code.c2tnb431r1.ordinal(), CURVE_ANSI_TNB431R1); } @Override public int getCurveCodeByName(String curveName) throws InvalidParameterException { if (curveName == null) throw new InvalidParameterException(); ECCurve_Code c = ECCurve_NameToCode.get(curveName); if (c == null) throw new InvalidParameterException(curveName); return c.ordinal(); } /* * getECCurve * maps curvecode to the actual oid of the curve and * returns the PK11ParameterSpec */ private AlgorithmParameterSpec getECCurve(int curvecode) throws InvalidParameterException { OBJECT_IDENTIFIER oid; oid = mECCurve_CodeToCurve.get(curvecode); if (oid == null) throw new IllegalArgumentException("curvecode ="+curvecode); return new PK11ParameterSpec(ASN1Util.encode(oid)); } private AlgorithmParameterSpec getCurve(int strength) throws InvalidParameterException { OBJECT_IDENTIFIER oid; switch (strength) { case 112: oid = CURVE_SECG_P112R1; // == WTLS-6 // Can't get to curve SECG P-112R2 // Can't get to curve WTLS-8 (No oid for WTLS-8) break; case 113: oid = CURVE_SECG_T113R1; // == WTLS-4 // Can't get to curve SECG T-113R2 // Can't get to curve WTLS-1 (No oid for WTLS-1) break; case 128: oid = CURVE_SECG_P128R1; // Can't get to curve SECG P-128R2 break; case 131: oid = CURVE_SECG_T131R1; // Can't get to curve SECG T-131R2 break; case 160: oid = CURVE_SECG_P160R1; // == WTLS-7 (TLS-16) // Can't get to curve SECG P-160K1 (TLS-15) // Can't get to curve SECG P-160R2 (TLS-17) // Can't get to curve WTLS-9 (No oid for WTLS-9) break; case 163: oid = CURVE_SECG_T163K1; // == NIST K-163 == WTLS-3 (TLS-1) // Can't get to curve ANSI C2-PNB163V1 == WTLS-5 // Can't get to curve ANSI C2-PNB163V2 // Can't get to curve ANSI C2-PNB163V3 // Can't get to curve SECG T-163R1 (TLS-2) // Can't get to curve SECG T-163R2 == NIST B-163 (TLS-3) break; case 176: oid = CURVE_ANSI_PNB176V1; break; case 191: oid = CURVE_ANSI_TNB191V1; // Can't get to curve ANSI C2-TNB191V2 // Can't get to curve ANSI C2-TNB191V3 // Can't get to curve ANSI C2-ONB191V4 // Can't get to curve ANSI C2-ONB191V5 break; case 192: oid = CURVE_ANSI_P192V1; // == NIST P-192 == SECG P-192R1 (TLS-19) // Can't get to curve ANSI P-192V2 // Can't get to curve ANSI P-192V3 // Can't get to curve SECG P-192K1 (TLS-18) break; case 193: oid = CURVE_SECG_T193R1; // (TLS-4) // Can't get to curve SECG T-193R2 // (TLS-5) break; case 208: oid = CURVE_ANSI_PNB208W1; break; case 224: oid = CURVE_SECG_P224R1; // == NIST P-224 == WTLS-12 (TLS-21) // Can't get to curve SECG P-224K1 (TLS-20) break; case 233: oid = CURVE_SECG_T233R1; // == NIST B-233 == WTLS-11 (TLS-7) // Can't get to curve SECG T-233K1 == NIST K-233 == WTLS-10 (TLS-6) break; case 239: oid = CURVE_SECG_T239K1; // (TLS8) // Can't get to curve ANSI P-239V1 // Can't get to curve ANSI P-239V2 // Can't get to curve ANSI P-239V3 // Can't get to curve ANSI C2-TNB239V1 // Can't get to curve ANSI C2-TNB239V2 // Can't get to curve ANSI C2-TNB239V3 // Can't get to curve ANSI C2-ONB239V4 // Can't get to curve ANSI C2-ONB239V5 break; case 256: oid = CURVE_ANSI_P256V1; // == NIST P-256 == SECG P-256R1 (TLS-23) // Can't get to curve SECG P-256K1 (TLS-22) break; case 272: oid = CURVE_ANSI_PNB272W1; break; case 283: oid = CURVE_SECG_T283R1; // == NIST B-283 (TLS-10) // Can't get to curve SECG T-283K1 == NIST K-283 (TLS-9) break; case 304: oid = CURVE_ANSI_PNB304W1; break; case 359: oid = CURVE_ANSI_TNB359V1; break; case 368: oid = CURVE_ANSI_PNB368W1; break; case 384: oid = CURVE_SECG_P384R1; // == NIST P-384 (TLS-24) break; case 409: oid = CURVE_SECG_T409R1; // == NIST B-409 (TLS-12) // Can't get to curve SECG T-409K1 == NIST K-409 (TLS-11) break; case 431: oid = CURVE_ANSI_TNB431R1; break; case 521: oid = CURVE_SECG_P521R1; // == NIST P-521 (TLS-25) break; case 571: oid = CURVE_SECG_T571R1; // == NIST B-571 (TLS-14) // Can't get to curve SECG T-571K1 == NIST K-571 (TLS-13) break; default: throw new InvalidParameterException(); } return new PK11ParameterSpec(ASN1Util.encode(oid)); } /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Private members /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// private PK11Token token; private AlgorithmParameterSpec params; private KeyPairAlgorithm algorithm; private boolean mKeygenOnInternalToken; private boolean temporaryPairMode = false; // 1: sensitive // 0: insensitive // -1: sensitive if temporaryPairMode is false, // insensitive if temporaryPairMode is true // (the default depends on temporaryPairMode for backward // compatibility) private int sensitivePairMode = -1; // 1: extractable // 0: unextractable // -1: unspecified (token dependent) private int extractablePairMode = -1; } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11KeyWrapper.c000066400000000000000000000714011412550063600237450ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "_jni/org_mozilla_jss_pkcs11_PK11KeyWrapper.h" #include #include #include #include #include #include /* JSS includes */ #include #include #include #include #include #include "StaticVoidPointer.h" #include "jssconfig.h" #define MAX_PRIVATE_KEY_LEN MAX_RSA_MODULUS_LEN /* * This is bytes, not bits. A 2048-bit wrapped RSA private key takes up around * 1200 bytes, because lots of "helper" values are stored along with the * modulus and exponent. 4096 bytes will hold at least a 4096-bit RSA key. */ #define MAX_WRAPPED_KEY_LEN 4096 /*********************************************************************** * * PK11KeyWrapper.nativeWrapSymWithSym */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeWrapSymWithSym (JNIEnv *env, jobject this, jobject tokenObj, jobject toBeWrappedObj, jobject wrappingKeyObj, jobject algObj, jbyteArray ivBA) { PK11SymKey *wrapping = NULL; PK11SymKey *toBeWrapped = NULL; CK_MECHANISM_TYPE mech; SECItem wrapped; jbyteArray wrappedBA=NULL; SECItem *iv=NULL, *param=NULL; SECStatus status; /* initialize so we can goto finish */ wrapped.data = NULL; wrapped.len = 0; /* get wrapping key */ if( JSS_PK11_getSymKeyPtr(env, wrappingKeyObj, &wrapping)!= PR_SUCCESS) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to extract symmetric " "wrapping key"); return NULL; } /* get toBeWrapped key */ if( JSS_PK11_getSymKeyPtr(env, toBeWrappedObj, &toBeWrapped) != PR_SUCCESS){ JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to extract symmetric " "to be wrapped key"); return NULL; } /* get the mechanism */ mech = JSS_getPK11MechFromAlg(env, algObj); if(mech == CKM_INVALID_MECHANISM) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unrecognized algorithm"); goto finish; } /* get the parameter */ if( ivBA ) { iv = JSS_ByteArrayToSECItem(env, ivBA); if( iv == NULL ) { goto finish; /* exception was thrown */ } param = PK11_ParamFromIV(mech, iv); if( param == NULL ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to create mechanism" " parameter from initialization vector"); goto finish; } } /* setup space for wrapped key */ wrapped.len = MAX_WRAPPED_KEY_LEN; /* yuk! */ wrapped.data = PR_Malloc(wrapped.len); if(wrapped.data == NULL) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } /* perform the wrap */ status = PK11_WrapSymKey(mech, param, wrapping, toBeWrapped, &wrapped); if( status != SECSuccess ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Wrap operation failed on token"); goto finish; } /* package the wrapped data into a byte array */ wrappedBA = JSS_SECItemToByteArray(env, &wrapped); finish: if(iv) { SECITEM_FreeItem(iv, PR_TRUE /*freeit*/); } if(param) { SECITEM_FreeItem(param, PR_TRUE /*freeit*/); } SECITEM_FreeItem(&wrapped, PR_FALSE /*freeit*/); return wrappedBA; } /*********************************************************************** * * PK11KeyWrapper.nativeWrapSymWithPub */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeWrapSymWithPub (JNIEnv *env, jobject this, jobject tokenObj, jobject toBeWrappedObj, jobject wrappingKeyObj, jobject algObj, jobject paramsPtr, jlong paramsSize) { SECKEYPublicKey *wrapping = NULL; PK11SymKey *toBeWrapped = NULL; CK_MECHANISM_TYPE mech; CK_VOID_PTR params = NULL; SECItem paramItem; SECItem wrapped; jbyteArray wrappedBA=NULL; SECStatus status; /* initialize so we can goto finish */ wrapped.data = NULL; wrapped.len = 0; /* get wrapping key */ if( JSS_PK11_getPubKeyPtr(env, wrappingKeyObj, &wrapping)!= PR_SUCCESS) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to extract public " "wrapping key"); return NULL; } /* get toBeWrapped key */ if( JSS_PK11_getSymKeyPtr(env, toBeWrappedObj, &toBeWrapped) != PR_SUCCESS){ JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to extract symmetric " "to be wrapped key"); return NULL; } if (paramsPtr != NULL) { if (JSS_PR_getStaticVoidRef(env, paramsPtr, ¶ms) != PR_SUCCESS) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to extract parameters " "to pass with the wrapping mechanism"); return NULL; } } /* get the mechanism */ mech = JSS_getPK11MechFromAlg(env, algObj); if(mech == CKM_INVALID_MECHANISM) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unrecognized algorithm"); goto finish; } /* setup space for wrapped key */ wrapped.len = MAX_WRAPPED_KEY_LEN; /* yuk! */ wrapped.data = PR_Malloc(wrapped.len); if(wrapped.data == NULL) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } paramItem.data = params; paramItem.len = paramsSize; /* perform the wrap */ #ifdef HAVE_NSS_OAEP status = PK11_PubWrapSymKeyWithMechanism(wrapping, mech, ¶mItem, toBeWrapped, &wrapped); #else if (mech == CKM_RSA_PKCS_OAEP) { JSS_throwMsg(env, TOKEN_EXCEPTION, "RSA-OAEP not supported by the NSS version used to build JSS"); goto finish; } status = PK11_PubWrapSymKey(mech, wrapping, toBeWrapped, &wrapped); #endif if( status != SECSuccess ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Wrap operation failed on token"); goto finish; } /* package the wrapped data into a byte array */ wrappedBA = JSS_SECItemToByteArray(env, &wrapped); finish: SECITEM_FreeItem(&wrapped, PR_FALSE /*freeit*/); return wrappedBA; } /*********************************************************************** * * PK11KeyWrapper.nativeWrapPrivWithSym */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeWrapPrivWithSym (JNIEnv *env, jobject this, jobject tokenObj, jobject toBeWrappedObj, jobject wrappingKeyObj, jobject algObj, jbyteArray ivBA) { PK11SymKey *wrapping = NULL; SECKEYPrivateKey *toBeWrapped= NULL; CK_MECHANISM_TYPE mech; SECStatus status; SECItem wrapped; PK11SlotInfo *slot=NULL; jbyteArray wrappedBA=NULL; SECItem *iv=NULL, *param=NULL; /* setup space for wrapped key */ wrapped.len = MAX_WRAPPED_KEY_LEN; wrapped.data = PR_Malloc(wrapped.len); if(wrapped.data == NULL) { wrapped.len = 0; JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } /* get wrapping key */ if( JSS_PK11_getSymKeyPtr(env, wrappingKeyObj, &wrapping) != PR_SUCCESS) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to extract symmetric " "wrapping key"); return NULL; } /* get toBeWrapped key */ if( JSS_PK11_getPrivKeyPtr(env, toBeWrappedObj, &toBeWrapped) !=PR_SUCCESS){ JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to extract private " "to be wrapped key"); return NULL; } /* get the slot */ if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS) { /* exception was thrown */ goto finish; } /* Get the wrapping mechanism */ mech = getSupportedWrappingMechanism(env, algObj, slot); if(mech == CKM_INVALID_MECHANISM) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unrecognized algorithm"); goto finish; } /* get the mechanism parameter (IV) */ if( ivBA ) { iv = JSS_ByteArrayToSECItem(env, ivBA); if( iv == NULL ) { goto finish; /* exception was thrown */ } param = PK11_ParamFromIV(mech, iv); if( param == NULL ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to convert initialization vector to parameter"); goto finish; } } /* perform the wrap operation */ status = PK11_WrapPrivKey(slot, wrapping, toBeWrapped, mech, param, &wrapped, NULL /* wincx */ ); if(status != SECSuccess) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Wrapping operation failed on token"); goto finish; } PR_ASSERT(wrapped.len>0 && wrapped.data!=NULL); /* package the wrapped data into a byte array */ wrappedBA = JSS_SECItemToByteArray(env, &wrapped); /* fall through if an exception occurs */ finish: if(iv) { SECITEM_FreeItem(iv, PR_TRUE /*freeit*/); } if(param) { SECITEM_FreeItem(param, PR_TRUE /*freeit*/); } SECITEM_FreeItem(&wrapped, PR_FALSE /*freeit*/); return wrappedBA; } /*********************************************************************** * * PK11KeyWrapper.nativeUnwrapPrivWithSym */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeUnwrapPrivWithSym (JNIEnv *env, jclass clazz, jobject tokenObj, jobject unwrapperObj, jbyteArray wrappedBA, jobject wrapAlgObj, jobject typeAlgObj, jbyteArray publicValueBA, jbyteArray ivBA, jboolean temporary) { PK11SlotInfo *slot; PK11SymKey *unwrappingKey; SECKEYPrivateKey *privk=NULL; jobject privkObj=NULL; CK_MECHANISM_TYPE wrapType, keyTypeMech; CK_KEY_TYPE keyType; SECItem *wrapped=NULL, *iv=NULL, *param=NULL, *pubValue=NULL; SECItem label; /* empty secitem, doesn't need to be freed */ PRBool token; CK_ATTRIBUTE_TYPE attribs[4] = {0, 0, 0, 0}; int numAttribs = 0; CK_TOKEN_INFO tokenInfo; /* ideal defaults */ PRBool isSensitive = PR_TRUE; PRBool isExtractable = PR_FALSE; /* special case nethsm and lunasa*/ const int numManufacturerIDchars = 7; CK_UTF8CHAR nethsmManufacturerID[] = {'n','C','i','p','h','e','r'}; CK_UTF8CHAR lunasaManufacturerID[] = {'S','a','f','e','n','e','t'}; PRBool isNethsm = PR_TRUE; PRBool isLunasa = PR_TRUE; tokenInfo.manufacturerID[0] = 0; if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS) { /* exception was thrown */ goto finish; } if ( (PK11_GetTokenInfo(slot, &tokenInfo) == SECSuccess) && (tokenInfo.manufacturerID[0] != 0)) { int ix = 0; for(ix=0; ix < numManufacturerIDchars; ix++) { if (tokenInfo.manufacturerID[ix] != nethsmManufacturerID[ix]) { isNethsm = PR_FALSE; break; } } for(ix=0; ix < numManufacturerIDchars; ix++) { if (tokenInfo.manufacturerID[ix] != lunasaManufacturerID[ix]) { isLunasa = PR_FALSE; break; } } } else { isNethsm = PR_FALSE; isLunasa = PR_FALSE; } /* get unwrapping key */ if( JSS_PK11_getSymKeyPtr(env, unwrapperObj, &unwrappingKey) != PR_SUCCESS) { /* exception was thrown */ goto finish; } /* Get the wrapping mechanism */ wrapType = getSupportedWrappingMechanism(env, wrapAlgObj, slot); if(wrapType == CKM_INVALID_MECHANISM) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unknown algorithm"); goto finish; } /* get the mechanism parameter (IV) */ if( ivBA ) { iv = JSS_ByteArrayToSECItem(env, ivBA); if( iv == NULL ) { goto finish; /* exception was thrown */ } param = PK11_ParamFromIV(wrapType, iv); if( param == NULL ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to convert initialization vector to parameter"); goto finish; } } /* get wrapped key from byte array */ wrapped = JSS_ByteArrayToSECItem(env, wrappedBA); if( wrapped == NULL ) { /* exception was thrown */ goto finish; } /* initialize the label to be empty */ label.len = 0; label.data = NULL; /* get the public value */ pubValue = JSS_ByteArrayToSECItem(env, publicValueBA); if(pubValue == NULL ) { /* exception was thrown */ goto finish; } if( temporary ) { token = PR_FALSE; } else { token = PR_TRUE; } /* get key type */ keyTypeMech = JSS_getPK11MechFromAlg(env, typeAlgObj); if( keyTypeMech == CKM_INVALID_MECHANISM ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unrecognized key type algorithm"); goto finish; } keyType = PK11_GetKeyType(keyTypeMech, 0); /* special case nethsm and lunasa*/ if( isNethsm ) { isSensitive = PR_FALSE; isExtractable = PR_FALSE; } else if ( isLunasa) { isSensitive = PR_FALSE; isExtractable = PR_TRUE; } /* figure out which operations to enable for this key */ switch (keyType) { case CKK_RSA: numAttribs = 3; attribs[0] = CKA_SIGN; attribs[1] = CKA_SIGN_RECOVER; attribs[2] = CKA_UNWRAP; if (isExtractable) { attribs[3] = CKA_EXTRACTABLE; numAttribs = 4; } break; case CKK_EC: numAttribs = 1; attribs[0] = CKA_SIGN; if (isExtractable) { attribs[1] = CKA_EXTRACTABLE; numAttribs = 2; } break; case CKK_DSA: attribs[0] = CKA_SIGN; numAttribs = 1; break; case CKK_KEA: case CKK_DH: case CKK_X9_42_DH: attribs[0] = CKA_DERIVE; numAttribs = 1; break; default: /* unknown key type */ PR_ASSERT(PR_FALSE); attribs[0] = CKA_SIGN; numAttribs = 1; break; } /* perform the unwrap */ privk = PK11_UnwrapPrivKey(slot, unwrappingKey, wrapType, param, wrapped, &label, pubValue, token, isSensitive /*sensitive*/, keyType, attribs, numAttribs, NULL /*wincx*/); if( privk == NULL ) { char err[256] = {0}; PR_snprintf(err, 256, "Key Unwrap failed on token; keyType=%d", keyType); JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, err); goto finish; } /* stuff the privk into a Java private key object. This sets privk to * NULL */ privkObj = JSS_PK11_wrapPrivKey(env, &privk); finish: if(iv) { SECITEM_FreeItem(iv, PR_TRUE /*free iv*/); } if(param) { SECITEM_FreeItem(param, PR_TRUE /*free param*/); } if(wrapped) { SECITEM_FreeItem(wrapped, PR_TRUE /*free wrapped*/); } if(pubValue) { SECITEM_FreeItem(pubValue, PR_TRUE /*free pubValue*/); } PR_ASSERT(privk==NULL); PR_ASSERT( privkObj!=NULL || (*env)->ExceptionOccurred(env) ); return privkObj; } #define ALL_SYMKEY_OPS (CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP) /*********************************************************************** * * PK11KeyWrapper.nativeUnwrapSymWithSym */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeUnwrapSymWithSym (JNIEnv *env, jclass clazz, jobject tokenObj, jobject unwrapperObj, jbyteArray wrappedBA, jobject wrapAlgObj, jobject typeAlgObj, jint keyLen, jbyteArray ivBA, jint usageEnum, jboolean temporary) { PK11SymKey *symKey=NULL, *wrappingKey=NULL; CK_MECHANISM_TYPE wrappingMech, keyTypeMech; SECItem *wrappedKey=NULL, *iv=NULL, *param=NULL; jobject keyObj = NULL; CK_ULONG operation; CK_FLAGS flags; PRBool isPermanent = PR_FALSE; /* get key type */ keyTypeMech = JSS_getPK11MechFromAlg(env, typeAlgObj); if( keyTypeMech == CKM_INVALID_MECHANISM ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unrecognized key type algorithm"); goto finish; } /* get wrapping key */ if( JSS_PK11_getSymKeyPtr(env, unwrapperObj, &wrappingKey) != PR_SUCCESS) { /* exception was thrown */ goto finish; } /* get wrapping mechanism */ wrappingMech = JSS_getPK11MechFromAlg(env, wrapAlgObj); if( wrappingMech == CKM_INVALID_MECHANISM ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unrecognized wrapping algorithm"); goto finish; } /* get the mechanism parameter (IV) */ if (ivBA == NULL) { param = PK11_ParamFromIV(wrappingMech,NULL); } else { iv = JSS_ByteArrayToSECItem(env, ivBA); if( iv == NULL ) { goto finish; /* exception was thrown */ } param = PK11_ParamFromIV(wrappingMech, iv); if( param == NULL ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to convert initialization vector to parameter"); goto finish; } } /* get the wrapped key */ wrappedKey = JSS_ByteArrayToSECItem(env, wrappedBA); if( wrappedKey == NULL ) { /* exception was thrown */ goto finish; } if( usageEnum == -1 ) { operation = CKA_ENCRYPT; /* doesn't matter, flags will override */ flags = ALL_SYMKEY_OPS; } else { operation = JSS_symkeyUsage[usageEnum]; flags = 0; } if( temporary ) { isPermanent = PR_FALSE; } else { isPermanent = PR_TRUE; } if( isPermanent == PR_FALSE) { symKey = PK11_UnwrapSymKeyWithFlags(wrappingKey, wrappingMech, param, wrappedKey, keyTypeMech, operation, keyLen, flags); } else { symKey = PK11_UnwrapSymKeyWithFlagsPerm(wrappingKey, wrappingMech, param, wrappedKey, keyTypeMech, operation, keyLen, flags,isPermanent); } if( symKey == NULL ) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to unwrap key"); goto finish; } /* wrap the symmetric key in a Java object. This will clear symKey */ keyObj = JSS_PK11_wrapSymKey(env, &symKey); finish: if(wrappedKey) { SECITEM_FreeItem(wrappedKey, PR_TRUE /*free wrappedKey*/); } if(iv) { SECITEM_FreeItem(iv, PR_TRUE /*free iv*/); } if(param) { SECITEM_FreeItem(param, PR_TRUE /*free param*/); } if( symKey ) { PK11_FreeSymKey(symKey); } return keyObj; } /*********************************************************************** * * PK11KeyWrapper.nativeUnwrapSymWithPriv */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeUnwrapSymWithPriv (JNIEnv *env, jclass clazz, jobject tokenObj, jobject unwrapperObj, jbyteArray wrappedBA, jobject wrapAlgObj, jobject typeAlgObj, jint keyLen, jobject paramsPtr, jlong paramsSize, jint usageEnum) { PK11SymKey *symKey=NULL; CK_MECHANISM_TYPE keyTypeMech=0, mech=0; SECItem *wrappedKey=NULL; jobject keyObj=NULL; CK_VOID_PTR params; SECItem paramItem; SECKEYPrivateKey *wrappingKey=NULL; CK_ULONG operation; /* get key type */ keyTypeMech = JSS_getPK11MechFromAlg(env, typeAlgObj); if( keyTypeMech == CKM_INVALID_MECHANISM ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unrecognized key type algorithm"); goto finish; } /* get wrapping key */ if( JSS_PK11_getPrivKeyPtr(env, unwrapperObj, &wrappingKey) != PR_SUCCESS) { /* exception was thrown */ goto finish; } /* get the mechanism parameter (IV) */ if (paramsPtr != NULL) { if (JSS_PR_getStaticVoidRef(env, paramsPtr, ¶ms) != PR_SUCCESS) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to extract parameters " "to pass with the wrapping mechanism"); return NULL; } } /* get the wrapped key */ wrappedKey = JSS_ByteArrayToSECItem(env, wrappedBA); if( wrappedKey == NULL ) { /* exception was thrown */ goto finish; } if( usageEnum == -1 ) { /* !!!XXX If they didn't specify a usage, we'll assume decrypt because that's the most common case, and we can't specify more than one. See bug 135255. */ operation = CKA_DECRYPT; } else { operation = JSS_symkeyUsage[usageEnum]; } /* get the mechanism */ mech = JSS_getPK11MechFromAlg(env, wrapAlgObj); if(mech == CKM_INVALID_MECHANISM) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unrecognized algorithm"); goto finish; } paramItem.data = params; paramItem.len = paramsSize; #ifdef HAVE_NSS_OAEP symKey = PK11_PubUnwrapSymKeyWithMechanism(wrappingKey, mech, ¶mItem, wrappedKey, keyTypeMech, operation, keyLen); #else if (mech == CKM_RSA_PKCS_OAEP) { JSS_throwMsg(env, TOKEN_EXCEPTION, "RSA-OAEP not supported by the NSS version used to build JSS"); goto finish; } symKey = PK11_PubUnwrapSymKey(wrappingKey, wrappedKey, keyTypeMech, operation, keyLen); #endif if( symKey == NULL ) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to unwrap key"); goto finish; } /* Put the symmetric key into a Java object. This will clear symKey */ keyObj = JSS_PK11_wrapSymKey(env, &symKey); finish: if(wrappedKey) { SECITEM_FreeItem(wrappedKey, PR_TRUE /*free wrappedKey*/); } if( symKey ) { PK11_FreeSymKey(symKey); } return keyObj; } PK11SymKey *JSS_PK11_ImportSymKeyWithFlagsFIPS(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE operation, SECItem *key, CK_FLAGS flags, PRBool isPerm, void *wincx) { PK11SymKey *result = NULL; PK11SymKey *wrapper = NULL; SECStatus ret = SECFailure; unsigned int wrapped_len = 0; unsigned int wrapped_max = key->len + 64; unsigned char *wrapped_key = calloc(wrapped_max, sizeof(unsigned char)); SECItem wrapped_item = { siBuffer, wrapped_key, 0 }; SECItem *param = NULL; /* Steps: * 1. Generate a temporary key to encrypt and unwrap with, * 2. Encrypt our key to import using the wrapping key, * 3. Unwrap into the token using the wrapping key. */ #define FIPS_KEYGEN_ALGO CKM_AES_KEY_GEN #define FIPS_ENCRYPT_UNWRAP_ALGO CKM_AES_KEY_WRAP_PAD wrapper = PK11_KeyGen(slot, FIPS_KEYGEN_ALGO, NULL, 32, wincx); if (wrapper == NULL) { goto done; } param = PK11_GenerateNewParam(FIPS_ENCRYPT_UNWRAP_ALGO, wrapper); if (param == NULL) { goto done; } ret = PK11_Encrypt(wrapper, FIPS_ENCRYPT_UNWRAP_ALGO, param, wrapped_key, &wrapped_len, wrapped_max, key->data, key->len); if (ret != SECSuccess) { goto done; } wrapped_item.len = wrapped_len; result = PK11_UnwrapSymKeyWithFlagsPerm(wrapper, FIPS_ENCRYPT_UNWRAP_ALGO, param, &wrapped_item, type, operation, key->len, flags, isPerm); done: free(wrapped_key); SECITEM_FreeItem(param, PR_TRUE); if (wrapper != NULL) { PK11_DeleteTokenSymKey(wrapper); PK11_FreeSymKey(wrapper); } return result; } /*********************************************************************** * * PK11KeyWrapper.nativeUnwrapSymPlaintext */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11KeyWrapper_nativeUnwrapSymPlaintext (JNIEnv *env, jclass clazz, jobject tokenObj, jbyteArray wrappedBA, jobject typeAlgObj, jint usageEnum, jboolean temporary) { PK11SymKey *symKey=NULL; CK_MECHANISM_TYPE keyTypeMech; SECItem *wrappedKey=NULL; jobject keyObj = NULL; PK11SlotInfo *slot = NULL; CK_ULONG operation; CK_FLAGS flags; PRBool isPerm = PR_FALSE; /* get key type */ keyTypeMech = JSS_getPK11MechFromAlg(env, typeAlgObj); if( keyTypeMech == CKM_INVALID_MECHANISM ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unrecognized key type algorithm"); goto finish; } if( temporary ) { isPerm = PR_FALSE; } else { isPerm = PR_TRUE; } /* get the slot */ if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS) { /* exception was thrown */ goto finish; } /* get the wrapped key */ wrappedKey = JSS_ByteArrayToSECItem(env, wrappedBA); if( wrappedKey == NULL ) { /* exception was thrown */ goto finish; } if( usageEnum == -1 ) { operation = CKA_ENCRYPT; flags = ALL_SYMKEY_OPS; } else { operation = JSS_symkeyUsage[usageEnum]; flags = 0; } /* pull in the key */ if (PK11_IsFIPS()) { symKey = JSS_PK11_ImportSymKeyWithFlagsFIPS(slot, keyTypeMech, operation, wrappedKey, flags, isPerm, NULL); } else { symKey = PK11_ImportSymKeyWithFlags(slot, keyTypeMech, PK11_OriginUnwrap, operation, wrappedKey, flags, isPerm, NULL); } if( symKey == NULL ) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to unwrap key"); goto finish; } /* wrap the symmetric key in a Java object. This will clear symKey */ keyObj = JSS_PK11_wrapSymKey(env, &symKey); finish: if(wrappedKey) { SECITEM_FreeItem(wrappedKey, PR_TRUE /*free wrappedKey*/); } if( symKey ) { PK11_FreeSymKey(symKey); } return keyObj; } /*********************************************************************** * * J S S _ P K 1 1 _ g e t E r r o r S t r i n g * * Returns a simple error string for a given PKCS #11 error. */ char* JSS_PK11_getErrorString(CK_RV crv) { switch(crv) { case CKR_ATTRIBUTE_READ_ONLY: return "CKR_ATTRIBUTE_READ_ONLY"; case CKR_ATTRIBUTE_TYPE_INVALID: return "CKR_ATTRIBUTE_TYPE_INVALID"; case CKR_ATTRIBUTE_VALUE_INVALID: return "CKR_ATTRIBUTE_VALUE_INVALID"; case CKR_BUFFER_TOO_SMALL: return "CKR_BUFFER_TOO_SMALL"; case CKR_CRYPTOKI_NOT_INITIALIZED: return "CKR_CRYPTOKI_NOT_INITIALIZED"; case CKR_DEVICE_ERROR: return "CKR_DEVICE_ERROR"; case CKR_DEVICE_MEMORY: return "CKR_DEVICE_MEMORY"; case CKR_DEVICE_REMOVED: return "CKR_DEVICE_REMOVED"; case CKR_FUNCTION_CANCELED: return "CKR_FUNCTION_CANCELED"; case CKR_FUNCTION_FAILED: return "CKR_FUNCTION_FAILED"; case CKR_GENERAL_ERROR: return "CKR_GENERAL_ERROR"; case CKR_HOST_MEMORY: return "CKR_HOST_MEMORY"; case CKR_KEY_HANDLE_INVALID: return "CKR_KEY_HANDLE_INVALID"; case CKR_KEY_NOT_WRAPPABLE: return "CKR_KEY_NOT_WRAPPABLE"; case CKR_KEY_SIZE_RANGE: return "CKR_KEY_SIZE_RANGE"; case CKR_KEY_UNEXTRACTABLE: return "CKR_KEY_UNEXTRACTABLE"; case CKR_MECHANISM_INVALID: return "CKR_MECHANISM_INVALID"; case CKR_MECHANISM_PARAM_INVALID: return "CKR_MECHANISM_PARAM_INVALID"; case CKR_OK: return "CKR_OK"; case CKR_OPERATION_ACTIVE: return "CKR_OPERATION_ACTIVE"; case CKR_SESSION_CLOSED: return "CKR_SESSION_CLOSED"; case CKR_SESSION_HANDLE_INVALID: return "CKR_SESSION_HANDLE_INVALID"; case CKR_SESSION_READ_ONLY: return "CKR_SESSION_READ_ONLY"; case CKR_TEMPLATE_INCOMPLETE: return "CKR_TEMPLATE_INCOMPLETE"; case CKR_TEMPLATE_INCONSISTENT: return "CKR_TEMPLATE_INCONSISTENT"; case CKR_TOKEN_WRITE_PROTECTED: return "CKR_TOKEN_WRITE_PROTECTED"; case CKR_UNWRAPPING_KEY_HANDLE_INVALID: return "CKR_UNWRAPPING_KEY_HANDLE_INVALID"; case CKR_UNWRAPPING_KEY_SIZE_RANGE: return "CKR_UNWRAPPING_KEY_SIZE_RANGE"; case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT: return "CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT"; case CKR_USER_NOT_LOGGED_IN: return "CKR_USER_NOT_LOGGED_IN"; case CKR_WRAPPED_KEY_INVALID: return "CKR_WRAPPED_KEY_INVALID"; case CKR_WRAPPED_KEY_LEN_RANGE: return "CKR_WRAPPED_KEY_LEN_RANGE"; case CKR_WRAPPING_KEY_HANDLE_INVALID: return "CKR_WRAPPING_KEY_HANDLE_INVALID"; case CKR_WRAPPING_KEY_SIZE_RANGE: return "CKR_WRAPPING_KEY_SIZE_RANGE"; case CKR_WRAPPING_KEY_TYPE_INCONSISTENT: return "CKR_WRAPPING_KEY_TYPE_INCONSISTENT"; default: return "PKCS #11 error"; } } /* * Get the wrapping mechanism */ CK_MECHANISM_TYPE getSupportedWrappingMechanism(JNIEnv *env, jobject algObj, PK11SlotInfo *slot) { CK_MECHANISM_TYPE mech = JSS_getPK11MechFromAlg(env, algObj); /* * Currently, NSS has different definitions for the AES KeyWrap * mechanisms from the PKCS11 standard. * Below, we first check for support of the PKCS11 standard; * If supported, we go with that, if not, we try the NSS ones */ if ( mech == CKM_AES_KEY_WRAP || mech == CKM_NSS_AES_KEY_WRAP) { if (!PK11_DoesMechanism(slot, CKM_AES_KEY_WRAP)) { mech = CKM_NSS_AES_KEY_WRAP; } else { mech = CKM_AES_KEY_WRAP; } } else if ( mech == CKM_AES_KEY_WRAP_PAD || mech == CKM_NSS_AES_KEY_WRAP_PAD) { if (!PK11_DoesMechanism(slot, CKM_AES_KEY_WRAP_PAD)) { mech = CKM_NSS_AES_KEY_WRAP_PAD; } else { mech = CKM_AES_KEY_WRAP_PAD; } } return mech; } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11KeyWrapper.java000066400000000000000000000613541412550063600244520ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.interfaces.DSAPublicKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.AlgorithmParameterSpec; import java.util.Arrays; import javax.crypto.spec.OAEPParameterSpec; import javax.crypto.spec.RC2ParameterSpec; import org.mozilla.jss.crypto.Algorithm; import org.mozilla.jss.crypto.EncryptionAlgorithm; import org.mozilla.jss.crypto.HMACAlgorithm; import org.mozilla.jss.crypto.IVParameterSpec; import org.mozilla.jss.crypto.JSSOAEPParameterSpec; import org.mozilla.jss.crypto.KeyPairAlgorithm; import org.mozilla.jss.crypto.KeyWrapAlgorithm; import org.mozilla.jss.crypto.KeyWrapper; import org.mozilla.jss.crypto.PrivateKey; import org.mozilla.jss.crypto.SymmetricKey; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.util.NativeEnclosure; import org.mozilla.jss.util.NativeProxy; public final class PK11KeyWrapper implements KeyWrapper { private PK11Token token; private KeyWrapAlgorithm algorithm; private int state=UNINITIALIZED; private AlgorithmParameterSpec parameters=null; private SymmetricKey symKey=null; private PrivateKey privKey=null; private PublicKey pubKey=null; private byte[] IV=null; // states private static final int UNINITIALIZED=0; private static final int WRAP=1; private static final int UNWRAP=2; private PK11KeyWrapper() { } PK11KeyWrapper(PK11Token token, KeyWrapAlgorithm algorithm) { this.token = token; this.algorithm = algorithm; } @Override public void initWrap(SymmetricKey wrappingKey, AlgorithmParameterSpec parameters) throws InvalidKeyException, InvalidAlgorithmParameterException { initWrap(parameters); checkWrapper(wrappingKey); this.symKey = wrappingKey; } @Override public void initWrap(PublicKey wrappingKey, AlgorithmParameterSpec parameters) throws InvalidKeyException, InvalidAlgorithmParameterException { initWrap(parameters); checkWrapper(wrappingKey); this.pubKey = wrappingKey; } @Override public void initWrap() throws InvalidKeyException, InvalidAlgorithmParameterException { if( algorithm != KeyWrapAlgorithm.PLAINTEXT ) { throw new InvalidKeyException(algorithm + " requires a key"); } reset(); state = WRAP; } /** * Does everything that is key-independent for initializing a wrap. */ private void initWrap(AlgorithmParameterSpec parameters) throws InvalidAlgorithmParameterException { reset(); this.parameters = checkParams(parameters); state = WRAP; } @Override public void initUnwrap(PrivateKey unwrappingKey, AlgorithmParameterSpec parameters) throws InvalidKeyException, InvalidAlgorithmParameterException { initUnwrap(parameters); checkWrapper(unwrappingKey); this.privKey = unwrappingKey; } @Override public void initUnwrap(SymmetricKey unwrappingKey, AlgorithmParameterSpec parameters) throws InvalidKeyException, InvalidAlgorithmParameterException { initUnwrap(parameters); checkWrapper(unwrappingKey); this.symKey = unwrappingKey; } @Override public void initUnwrap() throws InvalidKeyException, InvalidAlgorithmParameterException { if( algorithm != KeyWrapAlgorithm.PLAINTEXT ) { throw new InvalidKeyException(algorithm + " requires a key"); } reset(); state = UNWRAP; } /** * Does the key-independent parts of initializing an unwrap. */ private void initUnwrap(AlgorithmParameterSpec parameters) throws InvalidAlgorithmParameterException { reset(); this.parameters = checkParams(parameters); state = UNWRAP; } /** * Makes sure the key is right for the algorithm. */ private void checkWrapper(PublicKey key) throws InvalidKeyException { if( key==null ) { throw new InvalidKeyException("Key is null"); } if( ! (key instanceof PK11PubKey) ) { throw new InvalidKeyException("Key is not a PKCS #11 key"); } KeyType type = null; try { type = KeyType.getKeyTypeFromAlgorithm(algorithm); if( (type == KeyType.RSA && !(key instanceof RSAPublicKey)) || // requires JAVA 1.5 // (type == KeyType.EC && !(key instanceof ECPublicKey)) || (type == KeyType.DSA && !(key instanceof DSAPublicKey)) ) { throw new InvalidKeyException("Key is not the right type for "+ "this algorithm"); } } catch( NoSuchAlgorithmException e ) { throw new RuntimeException("Unable to find algorithm (" + algorithm + ") from key type (" + type + ") : " + e.getMessage(), e); } } /** * Makes sure the key lives on the token and is right for the algorithm. */ private void checkWrapper(SymmetricKey key) throws InvalidKeyException { if( key==null ) { throw new InvalidKeyException("Key is null"); } try { if( ! (key instanceof PK11SymKey) ) { throw new InvalidKeyException("Key is not a PKCS #11 key"); } if( ((PK11SymKey)key).getKeyType() != KeyType.getKeyTypeFromAlgorithm(algorithm) ) { throw new InvalidKeyException("Key is not the right type for"+ " this algorithm"); } } catch( NoSuchAlgorithmException e ) { throw new RuntimeException("Unknown algorithm: " + e.getMessage(), e); } catch (Exception e) { throw new RuntimeException("Unable to check wrapper: " + e.getMessage(), e); } } /** * Makes sure the key is on the token and is right for the algorithm. */ private void checkWrapper(PrivateKey key) throws InvalidKeyException { if( key==null ) { throw new InvalidKeyException("Key is null"); } if( ! (key instanceof PK11PrivKey) ) { throw new InvalidKeyException("Key is not a PKCS #11 key"); } try { if( ((PK11PrivKey)key).getKeyType() != KeyType.getKeyTypeFromAlgorithm(algorithm) ) { throw new InvalidKeyException("Key is not the right type for"+ " this algorithm"); } } catch( NoSuchAlgorithmException e ) { throw new RuntimeException("Unknown algorithm: " + e.getMessage(), e); } } private AlgorithmParameterSpec checkParams(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException { if( ! algorithm.isValidParameterObject(params) ) { String name = "null"; if( params != null ) { name = params.getClass().getName(); } throw new InvalidAlgorithmParameterException( algorithm + " cannot use a " + name + " parameter"); } if (params instanceof IVParameterSpec) { IV = ((IVParameterSpec)params).getIV(); } else if (params instanceof javax.crypto.spec.IvParameterSpec) { IV = ((javax.crypto.spec.IvParameterSpec)params).getIV(); } else if (params instanceof RC2ParameterSpec) { IV = ((RC2ParameterSpec)params).getIV(); } if (algorithm == KeyWrapAlgorithm.RSA_OAEP && params != null && params instanceof OAEPParameterSpec) { params = new JSSOAEPParameterSpec((OAEPParameterSpec) params); } return params; } @Override public byte[] wrap(PrivateKey toBeWrapped) throws InvalidKeyException, IllegalStateException, TokenException { if( state != WRAP ) { throw new IllegalStateException(); } if( algorithm == KeyWrapAlgorithm.PLAINTEXT ) { throw new InvalidKeyException( "plaintext wrapping not supported"); } checkWrappee(toBeWrapped); if( symKey != null ) { assert( privKey==null && pubKey==null ); return nativeWrapPrivWithSym(token, toBeWrapped, symKey, algorithm, IV); } else { throw new InvalidKeyException( "Wrapping a private key with a public key is not supported"); /* assert( pubKey!=null && privKey==null && symKey==null ); return nativeWrapPrivWithPub(token, toBeWrapped, pubKey, algorithm, IV); */ } } @Override public byte[] wrap(SymmetricKey toBeWrapped) throws InvalidKeyException, IllegalStateException, TokenException { if( state != WRAP ) { throw new IllegalStateException(); } if( algorithm == KeyWrapAlgorithm.PLAINTEXT ) { throw new InvalidKeyException("plaintext wrapping not supported"); } checkWrappee(toBeWrapped); if( symKey != null ) { assert( privKey==null && pubKey==null ); return nativeWrapSymWithSym(token, toBeWrapped, symKey, algorithm, IV); } assert( pubKey!=null && privKey==null && symKey==null ); NativeProxy params = null; long params_size = 0; if (parameters != null) { try { ((NativeEnclosure) parameters).open(); params = ((NativeEnclosure) parameters).mPointer; params_size = ((NativeEnclosure) parameters).mPointerSize; } catch (Exception e) { throw new TokenException(e.getMessage(), e); } } try { return nativeWrapSymWithPub(token, toBeWrapped, pubKey, algorithm, params, params_size); } finally { if (parameters != null) { try { ((NativeEnclosure) parameters).close(); } catch (Exception e) { throw new TokenException(e.getMessage(), e); } } } } /** * Makes sure the key lives on the right token. */ private void checkWrappee(SymmetricKey symKey) throws InvalidKeyException { if( symKey == null ) { throw new InvalidKeyException("key to be wrapped is null"); } if( ! (symKey instanceof PK11SymKey) ) { throw new InvalidKeyException("key to be wrapped is not a "+ "PKCS #11 key"); } } /** * Makes sure the key lives on the right token. */ private void checkWrappee(PrivateKey privKey) throws InvalidKeyException { if( privKey == null ) { throw new InvalidKeyException("key to be wrapped is null"); } if( ! (privKey instanceof PK11PrivKey) ) { throw new InvalidKeyException("key to be wrapped is not a "+ "PKCS #11 key"); } } /** * Wrap a symmetric with a symmetric */ private static native byte[] nativeWrapSymWithSym(PK11Token token, SymmetricKey toBeWrapped, SymmetricKey wrappingKey, KeyWrapAlgorithm alg, byte[] IV) throws TokenException; /** * Wrap a symmetric with a public */ private static native byte[] nativeWrapSymWithPub(PK11Token token, SymmetricKey toBeWrapped, PublicKey wrappingKey, KeyWrapAlgorithm alg, NativeProxy params, long params_size) throws TokenException; /** * Wrap a private with a symmetric */ private static native byte[] nativeWrapPrivWithSym(PK11Token token, PrivateKey toBeWrapped, SymmetricKey wrappingKey, KeyWrapAlgorithm alg, byte[] IV) throws TokenException; /** * Wrap a private with a public. * NOTE: This operation is not supported by the security library. private static native byte[] nativeWrapPrivWithPub(PK11Token token, PrivateKey toBeWrapped, PublicKey wrappingKey, KeyWrapAlgorithm alg, byte[] IV) throws TokenException; */ /** * Unwraps a private key, creating a permanent private key object. * A permanent private key object resides on a token until it is * explicitly deleted from the token. */ @Override public PrivateKey unwrapPrivate(byte[] wrapped, PrivateKey.Type type, PublicKey publicKey) throws TokenException, InvalidKeyException, IllegalStateException { return baseUnwrapPrivate(wrapped, type, publicKey, false); } /** * Unwraps a private key, creating a temporary private key object. * A temporary * private key is one that does not permanently reside on a token. * As soon as it is garbage-collected, it is gone forever. */ @Override public PrivateKey unwrapTemporaryPrivate(byte[] wrapped, PrivateKey.Type type, PublicKey publicKey) throws TokenException, InvalidKeyException, IllegalStateException { return baseUnwrapPrivate(wrapped, type, publicKey, true); } private PrivateKey baseUnwrapPrivate(byte[] wrapped, PrivateKey.Type type, PublicKey publicKey, boolean temporary) throws TokenException, InvalidKeyException, IllegalStateException { if( state != UNWRAP ) { throw new IllegalStateException(); } if( algorithm == KeyWrapAlgorithm.PLAINTEXT ) { throw new TokenException("plaintext unwrapping of private keys " + "is not supported"); } byte[] publicValue = extractPublicValue(publicKey, type); /* If first byte is null, omit it. * It can be null due to how BigInteger.toByteArray() is specified. */ if (publicValue.length > 0 && publicValue[0] == 0) { publicValue = Arrays.copyOfRange(publicValue, 1, publicValue.length); } if( symKey != null ) { assert(pubKey==null && privKey==null); PrivateKey importedKey = nativeUnwrapPrivWithSym( token, symKey, wrapped, algorithm, algFromType(type), publicValue, IV, temporary); if (!temporary && publicKey instanceof org.mozilla.jss.pkcs11.PK11PubKey) { try { token.importPublicKey( publicKey, true /* permanent */ ); } catch (Exception e) { // squash all exceptions // (some tokens cannot store the public key) } } return importedKey; } else { throw new InvalidKeyException("Unwrapping a private key with" + " a private key is not supported"); /* assert(privKey!=null && pubKey==null && symKey==null); return nativeUnwrapPrivWithPriv(token, privKey, wrapped, algorithm, algFromType(type), publicValue, IV, temporary ); */ } } /** * Extracts the "public value" from a public key. The public value is * used to construct the key identifier (CKA_ID). Also, the internal token * stores the EC DSA and EC public value along with the private key. */ private static byte[] extractPublicValue(PublicKey publicKey, PrivateKey.Type type) throws InvalidKeyException { /* this code should call a generic function which returns the * proper public value. */ if( publicKey == null ) { throw new InvalidKeyException("publicKey is null"); } if( type == PrivateKey.RSA ) { if( !(publicKey instanceof RSAPublicKey)) { throw new InvalidKeyException("Type of public key does not "+ "match type of private key which is RSA"); } return ((RSAPublicKey)publicKey).getModulus().toByteArray(); } else if(type == PrivateKey.EC) { if( !(publicKey instanceof PK11ECPublicKey) ) { throw new InvalidKeyException("Type of public key does not "+ "match type of private key which is EC"); } return ((PK11ECPublicKey)publicKey).getWByteArray(); } else if(type == PrivateKey.DSA) { if( !(publicKey instanceof DSAPublicKey) ) { throw new InvalidKeyException("Type of public key does not "+ "match type of private key which is DSA"); } return ((DSAPublicKey)publicKey).getY().toByteArray(); } else { throw new InvalidKeyException("Unknown private key type: " + type); } } @Override public SymmetricKey unwrapSymmetric(byte[] wrapped, SymmetricKey.Type type, SymmetricKey.Usage usage, int keyLen) throws TokenException, IllegalStateException, InvalidAlgorithmParameterException { return unwrapSymmetric(wrapped, type, usage.ordinal(), keyLen); } @Override public SymmetricKey unwrapSymmetric(byte[] wrapped, SymmetricKey.Type type, int keyLen) throws TokenException, IllegalStateException, InvalidAlgorithmParameterException { return unwrapSymmetric(wrapped, type, -1, keyLen); } @Override public SymmetricKey unwrapSymmetricPerm(byte[] wrapped, SymmetricKey.Type type, SymmetricKey.Usage usage, int keyLen) throws TokenException, IllegalStateException, InvalidAlgorithmParameterException { return unwrapSymmetricPerm(wrapped, type, usage.ordinal(), keyLen); } @Override public SymmetricKey unwrapSymmetricPerm(byte[] wrapped, SymmetricKey.Type type, int keyLen) throws TokenException, IllegalStateException, InvalidAlgorithmParameterException { return unwrapSymmetricPerm(wrapped, type, -1, keyLen); } private SymmetricKey unwrapSymmetricPerm(byte[] wrapped, SymmetricKey.Type type, int usageEnum, int keyLen) throws TokenException, IllegalStateException, InvalidAlgorithmParameterException { if( state != UNWRAP ) { throw new IllegalStateException(); } /* Since we want permanent,make the temporary arg false */ boolean temporary = false; if( (! algorithm.isPadded()) && (type == SymmetricKey.RC4) ) { if( keyLen <= 0 ) { throw new InvalidAlgorithmParameterException( "RC4 keys wrapped in unpadded algorithms need key length"+ " specified when unwrapping"); } } else { // Don't use the key length keyLen = 0; } if( algorithm == KeyWrapAlgorithm.PLAINTEXT ) { return nativeUnwrapSymPlaintext(token, wrapped, algFromType(type), usageEnum,temporary ); } else { if( symKey != null ) { assert(pubKey==null && privKey==null); return nativeUnwrapSymWithSym(token, symKey, wrapped, algorithm, algFromType(type), keyLen, IV, usageEnum,temporary); } else { assert(privKey!=null && pubKey==null && symKey==null); throw new TokenException("We do not support permnament unwrapping with private key."); } } } private SymmetricKey unwrapSymmetric(byte[] wrapped, SymmetricKey.Type type, int usageEnum, int keyLen) throws TokenException, IllegalStateException, InvalidAlgorithmParameterException { if( state != UNWRAP ) { throw new IllegalStateException(); } if( (! algorithm.isPadded()) && (type == SymmetricKey.RC4) ) { if( keyLen <= 0 ) { throw new InvalidAlgorithmParameterException( "RC4 keys wrapped in unpadded algorithms need key length"+ " specified when unwrapping"); } } else { // Don't use the key length //keyLen = 0; } /* Since we DONT want permanent,make the temporary arg true */ boolean temporary = true; if( algorithm == KeyWrapAlgorithm.PLAINTEXT ) { return nativeUnwrapSymPlaintext(token, wrapped, algFromType(type), usageEnum, temporary ); } if( symKey != null ) { assert(pubKey==null && privKey==null); return nativeUnwrapSymWithSym(token, symKey, wrapped, algorithm, algFromType(type), keyLen, IV, usageEnum,temporary); } assert(privKey!=null && pubKey==null && symKey==null); NativeProxy params = null; long params_size = 0; if (parameters != null) { try { ((NativeEnclosure) parameters).open(); params = ((NativeEnclosure) parameters).mPointer; params_size = ((NativeEnclosure) parameters).mPointerSize; } catch (Exception e) { throw new TokenException(e.getMessage(), e); } } try { return nativeUnwrapSymWithPriv(token, privKey, wrapped, algorithm, algFromType(type), keyLen, params, params_size, usageEnum); } finally { if (parameters != null) { try { ((NativeEnclosure) parameters).close(); } catch (Exception e) { throw new TokenException(e.getMessage(), e); } } } } private static Algorithm algFromType(PrivateKey.Type type) { if (type == PrivateKey.RSA) { return KeyPairAlgorithm.RSAFamily; } else if (type == PrivateKey.DSA) { return KeyPairAlgorithm.DSAFamily; } else { assert( type == PrivateKey.EC); return KeyPairAlgorithm.ECFamily; } } private static Algorithm algFromType(SymmetricKey.Type type) { if( type == SymmetricKey.DES ) { return EncryptionAlgorithm.DES_ECB; } else if( type == SymmetricKey.DES3 ) { return EncryptionAlgorithm.DES3_ECB; } else if( type == SymmetricKey.AES ) { return EncryptionAlgorithm.AES_128_ECB; }else if( type == SymmetricKey.RC4 ) { return EncryptionAlgorithm.RC4; } else if( type == SymmetricKey.AES ) { return EncryptionAlgorithm.AES_128_ECB; } else if( type == SymmetricKey.SHA1_HMAC) { return HMACAlgorithm.SHA1; } else { assert( type == SymmetricKey.RC2 ); return EncryptionAlgorithm.RC2_CBC; } } /** * Unwrap a private with a symmetric. */ private static native PrivateKey nativeUnwrapPrivWithSym(PK11Token token, SymmetricKey unwrappingKey, byte[] wrappedKey, KeyWrapAlgorithm alg, Algorithm type, byte[] publicValue, byte[] IV, boolean temporary) throws TokenException; /** * Unwrap a private with a private. * NOTE: this is not supported by the security library. private static native PrivateKey nativeUnwrapPrivWithPriv(PK11Token token, PrivateKey unwrappingKey, byte[] wrappedKey, KeyWrapAlgorithm alg, Algorithm type, byte[] publicValue, byte[] IV, boolean temporary) throws TokenException; */ /** * Unwrap a symmetric with a symmetric. */ private static native SymmetricKey nativeUnwrapSymWithSym(PK11Token token, SymmetricKey unwrappingKey, byte[] wrappedKey, KeyWrapAlgorithm alg, Algorithm type, int keyLen, byte[] IV, int usageEnum, boolean temporary) throws TokenException; /** * Unwrap a symmetric with a private. */ private static native SymmetricKey nativeUnwrapSymWithPriv(PK11Token token, PrivateKey unwrappingKey, byte[] wrappedKey, KeyWrapAlgorithm alg, Algorithm type, int keyLen, NativeProxy params, long params_size, int usageEnum) throws TokenException; private static native SymmetricKey nativeUnwrapSymPlaintext(PK11Token token, byte[] wrappedKey, Algorithm type, int usageEnum, boolean temporary); private void reset() { state = UNINITIALIZED; symKey = null; privKey = null; pubKey = null; parameters = null; IV = null; } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11MessageDigest.c000066400000000000000000000111271412550063600243770ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "_jni/org_mozilla_jss_pkcs11_PK11MessageDigest.h" #include #include #include #include #include /* JSS includes */ #include #include #include #include #include /*********************************************************************** * * PK11MessageDigest.initDigest * */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11MessageDigest_initDigest (JNIEnv *env, jclass clazz, jobject algObj) { SECOidTag alg; PK11Context *context=NULL; alg = JSS_getOidTagFromAlg(env, algObj); PR_ASSERT( alg != SEC_OID_UNKNOWN ); /* we checked already in Java */ context = PK11_CreateDigestContext(alg); if( context == NULL ) { JSS_throwMsg(env, DIGEST_EXCEPTION, "Unable to create digest context"); return NULL; } return JSS_PK11_wrapCipherContextProxy(env, &context); } /*********************************************************************** * * PK11MessageDigest.initHMAC * */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11MessageDigest_initHMAC (JNIEnv *env, jclass clazz, jobject tokenObj, jobject algObj, jobject keyObj) { PK11SymKey *origKey = NULL, *newKey=NULL; PK11Context *context = NULL; CK_MECHANISM_TYPE mech; SECItem param; jobject contextObj=NULL; bool freeNewKey = true; mech = JSS_getPK11MechFromAlg(env, algObj); PR_ASSERT( mech != CKM_INVALID_MECHANISM ); /* we checked already in Java */ if( JSS_PK11_getSymKeyPtr(env, keyObj, &origKey) != PR_SUCCESS ) { /* exception was thrown */ goto finish; } /* copy the key, setting the CKA_SIGN attribute */ newKey = PK11_CopySymKeyForSigning(origKey, mech); /* For some key on the hsm, this call could fail, but the key may work anyway */ if( newKey == NULL ) { newKey = origKey; freeNewKey = false; } param.data = NULL; param.len = 0; context = PK11_CreateContextBySymKey(mech, CKA_SIGN, newKey, ¶m); if( context == NULL ) { JSS_throwMsg(env, DIGEST_EXCEPTION, "Unable to initialize digest context"); goto finish; } contextObj = JSS_PK11_wrapCipherContextProxy(env, &context); finish: if(freeNewKey) { /* SymKeys are ref counted, and the context will free it's ref * when it is destroyed */ PK11_FreeSymKey(newKey); } return contextObj; } /*********************************************************************** * * PK11MessageDigest.update * */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11MessageDigest_update (JNIEnv *env, jclass clazz, jobject proxyObj, jbyteArray inbufBA, jint offset, jint len) { PK11Context *context = NULL; jbyte* bytes = NULL; jsize length = 0; if( JSS_PK11_getCipherContext(env, proxyObj, &context) != PR_SUCCESS ) { /* exception was thrown */ goto finish; } if (!JSS_RefByteArray(env, inbufBA, &bytes, &length) || length < offset+len) { goto finish; } if( PK11_DigestOp(context, (unsigned char*)(bytes+offset), len) != SECSuccess ) { JSS_throwMsg(env, DIGEST_EXCEPTION, "Digest operation failed"); goto finish; } finish: JSS_DerefByteArray(env, inbufBA, bytes, JNI_ABORT); } /*********************************************************************** * * PK11MessageDigest.digest * */ JNIEXPORT jint JNICALL Java_org_mozilla_jss_pkcs11_PK11MessageDigest_digest (JNIEnv *env, jclass clazz, jobject proxyObj, jbyteArray outbuf, jint offset, jint len) { PK11Context *context=NULL; jbyte *bytes=NULL; jsize length = 0; SECStatus status; unsigned int outLen = 0; if( JSS_PK11_getCipherContext(env, proxyObj, &context) != PR_SUCCESS) { /* exception was thrown */ goto finish; } if (!JSS_RefByteArray(env, outbuf, &bytes, &length) || length < offset+len) { ASSERT_OUTOFMEM(env); goto finish; } status = PK11_DigestFinal(context, (unsigned char*)(bytes+offset), &outLen, len); if( status != SECSuccess ) { JSS_throwMsg(env, DIGEST_EXCEPTION, "Error occurred while performing" " digest operation"); goto finish; } finish: JSS_DerefByteArray(env, outbuf, bytes, 0); return outLen; } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11MessageDigest.java000066400000000000000000000077101412550063600251010ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import org.mozilla.jss.crypto.*; import java.security.DigestException; import java.security.NoSuchAlgorithmException; import java.security.InvalidKeyException; /** * Message Digesting with PKCS #11. */ public final class PK11MessageDigest extends JSSMessageDigest implements java.lang.AutoCloseable { private PK11Token token; private CipherContextProxy digestProxy; private PK11SymKey hmacKey; private DigestAlgorithm alg; PK11MessageDigest(PK11Token token, DigestAlgorithm alg) throws NoSuchAlgorithmException, DigestException { this.token = token; this.alg = alg; if( ! token.doesAlgorithm(alg) ) { throw new NoSuchAlgorithmException(); } reset(); } @Override public void initHMAC(SymmetricKey key) throws DigestException, InvalidKeyException { if( ! (alg instanceof HMACAlgorithm || alg instanceof CMACAlgorithm) ) { throw new DigestException("Digest is not an HMAC or CMAC digest"); } if( ! (key instanceof PK11SymKey) ) { throw new InvalidKeyException("HMAC key is not a PKCS #11 key"); } hmacKey = (PK11SymKey) key; this.digestProxy = initHMAC(token, alg, hmacKey); } @Override public void update(byte[] input, int offset, int len) throws DigestException { if( digestProxy == null ) { throw new DigestException("Digest not correctly initialized"); } if( input.length < offset+len ) { throw new IllegalArgumentException( "Input buffer is not large enough for offset and length"); } update(digestProxy, input, offset, len); } @Override public int digest(byte[] outbuf, int offset, int len) throws DigestException { if( digestProxy == null ) { throw new DigestException("Digest not correctly initialized"); } if( outbuf.length < offset+len ) { throw new IllegalArgumentException( "Output buffer is not large enough for offset and length"); } int retval = digest(digestProxy, outbuf, offset, len); reset(); return retval; } @Override public void reset() throws DigestException { if( ! (alg instanceof HMACAlgorithm || alg instanceof CMACAlgorithm) ) { // This is a regular digest, so we have enough information // to initialize the context this.digestProxy = initDigest(alg); } else if( hmacKey != null ) { // This is an HMAC digest, and we have a key this.digestProxy = initHMAC(token, alg, hmacKey); } else { // this is an HMAC digest for which we don't have the key yet, // we have to wait to construct the context this.digestProxy = null; } } @Override public DigestAlgorithm getAlgorithm() { return alg; } private static native CipherContextProxy initDigest(DigestAlgorithm alg) throws DigestException; private static native CipherContextProxy initHMAC(PK11Token token, DigestAlgorithm alg, PK11SymKey key) throws DigestException; private static native void update(CipherContextProxy proxy, byte[] inbuf, int offset, int len); private static native int digest(CipherContextProxy proxy, byte[] outbuf, int offset, int len); @Override public void finalize() throws Throwable { close(); } @Override public void close() throws Exception { if (digestProxy != null) { try { digestProxy.close(); } finally { digestProxy = null; } } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11Module.c000066400000000000000000000147721412550063600231110ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "_jni/org_mozilla_jss_pkcs11_PK11Module.h" #include #include #include #include #include #include "pk11util.h" #include #include #include "jss_exceptions.h" /*********************************************************************** * Class: org_mozilla_jss_pkcs11_PK11Module * Method: getName * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_org_mozilla_jss_pkcs11_PK11Module_getName (JNIEnv *env, jobject this) { SECMODModule *module; jstring nameString=NULL; PR_ASSERT(env!=NULL && this!=NULL); if( JSS_PK11_getModulePtr(env, this, &module) != PR_SUCCESS) { goto finish; } PR_ASSERT(module->commonName != NULL); nameString = (*env)->NewStringUTF(env, module->commonName); finish: PR_ASSERT( nameString || (*env)->ExceptionOccurred(env) ); return nameString; } /*********************************************************************** * Class: org_mozilla_jss_pkcs11_PK11Module * Method: getLibraryName * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_org_mozilla_jss_pkcs11_PK11Module_getLibraryName (JNIEnv *env, jobject this) { SECMODModule *module; jstring libName = NULL; PR_ASSERT(env!=NULL && this!=NULL); if( JSS_PK11_getModulePtr(env, this, &module) != PR_SUCCESS) { goto finish; } PR_ASSERT(module->dllName != NULL); libName = (*env)->NewStringUTF(env, module->dllName); finish: PR_ASSERT( libName || (*env)->ExceptionOccurred(env) ); return libName; } /*********************************************************************** * Class: org_mozilla_jss_pkcs11_PK11Module * Method: putTokensInVector * Signature: (Ljava/util/Vector;)V */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11Module_putTokensInVector (JNIEnv *env, jobject this, jobject vector) { SECMODModule *module; jclass vectorClass; jmethodID addElement; jobject token; PK11SlotInfo *slot; int i; PR_ASSERT(env!=NULL && this!=NULL && vector!=NULL); /*************************** * Get Vector JNI ids ***************************/ vectorClass = (*env)->GetObjectClass(env, vector); if(vectorClass==NULL) goto finish; addElement = (*env)->GetMethodID(env, vectorClass, VECTOR_ADD_ELEMENT_NAME, VECTOR_ADD_ELEMENT_SIG); if(addElement==NULL) goto finish; /*************************** * Get the PKCS #11 module ***************************/ if( JSS_PK11_getModulePtr(env, this, &module) != PR_SUCCESS) goto finish; /************************** * Loop over slots **************************/ for(i=0; i < module->slotCount; i++) { if (PK11_IsPresent(module->slots[i])) { char *tokenname; tokenname = PK11_GetTokenName(module->slots[i]); /* ignore if the token has no name */ if( tokenname!=NULL && tokenname[0]!='\0' ) { /* turn the slot into a PK11Token */ slot = PK11_ReferenceSlot(module->slots[i]); PR_ASSERT(slot!=NULL); token = JSS_PK11_wrapPK11Token(env, &slot); /* stick the PK11Token in the Vector */ (*env)->CallVoidMethod(env, vector, addElement, token); } } } finish: return; } /*********************************************************************** * * J S S _ P K 1 1 _ w r a p P K 1 1 M o d u l e * * Turns a SECMODModule* C structure into a PK11Module Java object. * * INPUTS * ptr * Address of a SECMODModule *. This pointer will be copied * into the new Java object, then set to NULL. * RETURNS * A new Java PK11Module object, or NULL if an exception was thrown. * In any case, the ptr parameter is eaten. */ jobject JSS_PK11_wrapPK11Module(JNIEnv *env, SECMODModule **module) { jclass moduleClass; jmethodID constructor; jobject newModule=NULL; jbyteArray pointer; PR_ASSERT(env!=NULL && module!=NULL && *module!=NULL); pointer = JSS_ptrToByteArray(env, (void*)*module); /* * Lookup the class and constructor */ moduleClass = (*env)->FindClass(env, PK11MODULE_CLASS_NAME); if(moduleClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } constructor = (*env)->GetMethodID( env, moduleClass, PLAIN_CONSTRUCTOR, PK11MODULE_CONSTRUCTOR_SIG); if(constructor == NULL) { ASSERT_OUTOFMEM(env); goto finish; } /* * Call the constructor */ newModule = (*env)->NewObject(env, moduleClass, constructor, pointer); finish: if(newModule==NULL) { SECMOD_DestroyModule(*module); } *module = NULL; return newModule; } /*********************************************************************** * * J S S _ P K 1 1 _ g e t M o d u l e P t r * * Retrieve the SECMODModule pointer of the given PK11Module. * * INPUTS * module * A reference to a Java PK11Module. * ptr * Address of a SECMODModule * that will be loaded with the * SECMODModule pointer of the given PK11Module. * RETURNS * PR_FAILURE if an exception was thrown, or PR_SUCCESS if the * peration succeeded. */ PRStatus JSS_PK11_getModulePtr(JNIEnv *env, jobject module, SECMODModule **ptr) { PR_ASSERT(env!=NULL && module!=NULL && ptr!=NULL); return JSS_getPtrFromProxyOwner(env, module, PK11MODULE_PROXY_FIELD, PK11MODULE_PROXY_SIG, (void**)ptr); } /********************************************************************** * ModuleProxy.releaseNativeResources */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_ModuleProxy_releaseNativeResources (JNIEnv *env, jobject this) { SECMODModule *module = NULL; if (JSS_getPtrFromProxy(env, this, (void **)&module) != PR_SUCCESS) { ASSERT_OUTOFMEM(env); return; } if (module != NULL) { SECMOD_DestroyModule(module); } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11Module.java000066400000000000000000000030651412550063600236010ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.crypto.CryptoToken; public final class PK11Module { private PK11Module() { throw new RuntimeException("PK11Module default constructor"); } /** * This constructor should only be called from native code. */ private PK11Module(byte[] pointer) { assert(pointer!=null); moduleProxy = new ModuleProxy(pointer); reloadTokens(); } /** * Returns the common name of this module. */ public native String getName(); /** * Returns the name of the shared library implementing this module. */ public native String getLibraryName(); /** * Get the CryptoTokens provided by this module. * * @return An enumeration of CryptoTokens that come from this module. */ public synchronized Enumeration getTokens() { return tokenVector.elements(); } /** * Re-load the list of this module's tokens. This function is private * to JSS. */ public synchronized void reloadTokens() { tokenVector = new Vector<>(); putTokensInVector(tokenVector); } private native void putTokensInVector(Vector tokens); private Vector tokenVector; private ModuleProxy moduleProxy; } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11ParameterSpec.java000066400000000000000000000010201412550063600250740ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import java.security.spec.AlgorithmParameterSpec; public final class PK11ParameterSpec implements AlgorithmParameterSpec { public PK11ParameterSpec(byte [] derBlob) { blob = derBlob; } public byte [] getEncoded() { return blob; } private byte [] blob; } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11PrivKey.c000066400000000000000000000466761412550063600232650ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "_jni/org_mozilla_jss_pkcs11_PrivateKeyProxy.h" #include #include #include #include #include #include #include #include #include #include #include #include "pk11util.h" #include "java_ids.h" /*********************************************************************** * * J S S _ P K 1 1 _ w r a p P r i v K e y * privk: will be stored in a Java wrapper. * Returns: a new PK11PrivKey, or NULL if an exception occurred. */ jobject JSS_PK11_wrapPrivKey(JNIEnv *env, SECKEYPrivateKey **privk) { jclass keyClass; jmethodID constructor; jbyteArray ptrArray; jobject Key=NULL; const char *className = NULL; PR_ASSERT(env!=NULL && privk!=NULL && *privk!=NULL); /* Find the class */ switch( (*privk)->keyType ) { case rsaKey: className = "org/mozilla/jss/pkcs11/PK11RSAPrivateKey"; break; case dsaKey: className = "org/mozilla/jss/pkcs11/PK11DSAPrivateKey"; break; case ecKey: className = "org/mozilla/jss/pkcs11/PK11ECPrivateKey"; break; default: className = "org/mozilla/jss/pkcs11/PK11PrivKey"; break; } keyClass = (*env)->FindClass(env, className); if(keyClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } /* find the constructor */ constructor = (*env)->GetMethodID(env, keyClass, "", "([B)V"); if(constructor == NULL) { ASSERT_OUTOFMEM(env); goto finish; } /* convert the pointer to a byte array */ ptrArray = JSS_ptrToByteArray(env, (void*)*privk); if(ptrArray == NULL) { goto finish; } /* call the constructor */ Key = (*env)->NewObject(env, keyClass, constructor, ptrArray); finish: if(Key == NULL) { SECKEY_DestroyPrivateKey(*privk); } *privk = NULL; return Key; } /*********************************************************************** * PK11PrivKey.verifyKeyIsOnToken */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11PrivKey_verifyKeyIsOnToken (JNIEnv *env, jobject this, jobject token) { SECKEYPrivateKey *key = NULL; PK11SlotInfo *slot = NULL; PK11SlotInfo *keySlot = NULL; PK11SlotInfo *cryptoSlot = NULL; if( JSS_PK11_getPrivKeyPtr(env, this, &key) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } if( JSS_PK11_getTokenSlotPtr(env, token, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } keySlot = PK11_GetSlotFromPrivateKey(key); if (PK11_IsInternalKeySlot(keySlot)) { cryptoSlot = PK11_GetInternalSlot(); /* hack for internal module */ if(slot != keySlot && slot != cryptoSlot) { JSS_throwMsg(env, NO_SUCH_ITEM_ON_TOKEN_EXCEPTION, "Key is not present on this token"); goto finish; } } else if(keySlot != slot) { JSS_throwMsg(env, NO_SUCH_ITEM_ON_TOKEN_EXCEPTION, "Key is not present on this token"); goto finish; } finish: if(keySlot != NULL) { PK11_FreeSlot(keySlot); } if (cryptoSlot != NULL) { PK11_FreeSlot(cryptoSlot); } } /* * PK11PrivKey.getKeyType * * Returns: The KeyType of this key. */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11PrivKey_getKeyType (JNIEnv *env, jobject this) { PRThread * VARIABLE_MAY_NOT_BE_USED pThread; SECKEYPrivateKey *privk; KeyType keyType; char* keyTypeFieldName; jclass keyTypeClass; jfieldID keyTypeField; jobject keyTypeObject = NULL; PR_ASSERT(env!=NULL && this!=NULL); pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); PR_ASSERT(pThread != NULL); if(JSS_PK11_getPrivKeyPtr(env, this, &privk) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL ); goto finish; } PR_ASSERT(privk!=NULL); keyType = SECKEY_GetPrivateKeyType(privk); switch(keyType) { case nullKey: keyTypeFieldName = NULL_KEYTYPE_FIELD; break; case rsaKey: keyTypeFieldName = RSA_KEYTYPE_FIELD; break; case dsaKey: keyTypeFieldName = DSA_KEYTYPE_FIELD; break; case fortezzaKey: keyTypeFieldName = FORTEZZA_KEYTYPE_FIELD; break; case dhKey: keyTypeFieldName = DH_KEYTYPE_FIELD; break; case keaKey: keyTypeFieldName = KEA_KEYTYPE_FIELD; break; case ecKey: keyTypeFieldName = EC_KEYTYPE_FIELD; break; default: PR_ASSERT(PR_FALSE); keyTypeFieldName = NULL_KEYTYPE_FIELD; break; } keyTypeClass = (*env)->FindClass(env, KEYTYPE_CLASS_NAME); if(keyTypeClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } keyTypeField = (*env)->GetStaticFieldID(env, keyTypeClass, keyTypeFieldName, KEYTYPE_FIELD_SIG); if(keyTypeField==NULL) { ASSERT_OUTOFMEM(env); goto finish; } keyTypeObject = (*env)->GetStaticObjectField( env, keyTypeClass, keyTypeField); if(keyTypeObject == NULL) { ASSERT_OUTOFMEM(env); goto finish; } finish: PR_DetachThread(); return keyTypeObject; } /* * PrivateKeyProxy.releaseNativeResources */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PrivateKeyProxy_releaseNativeResources (JNIEnv *env, jobject this) { SECKEYPrivateKey *privk = NULL; PRThread * VARIABLE_MAY_NOT_BE_USED pThread; PR_ASSERT(env!=NULL && this!=NULL); pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); PR_ASSERT(pThread != NULL); /* Get the SECKEYPrivateKey structure */ if(JSS_getPtrFromProxy(env, this, (void**) &privk) != PR_SUCCESS) { PR_ASSERT( PR_FALSE ); goto finish; } if (privk != NULL) { SECKEY_DestroyPrivateKey(privk); } finish: PR_DetachThread(); return; } /* * Given a PrivateKey object, extracts the SECKEYPrivateKey* and stores it * at the given address. * * privkObject: A JNI reference to a PrivateKey object. * ptr: Address of a SECKEYPrivateKey* that will receive the pointer. * Returns: PR_SUCCESS for success, PR_FAILURE if an exception was thrown. */ PRStatus JSS_PK11_getPrivKeyPtr(JNIEnv *env, jobject privkObject, SECKEYPrivateKey** ptr) { PR_ASSERT(env!=NULL && privkObject!=NULL); /* Get the pointer from the key proxy */ PR_ASSERT(sizeof(SECKEYPrivateKey*) == sizeof(void*)); return JSS_getPtrFromProxyOwner(env, privkObject, KEY_PROXY_FIELD, KEY_PROXY_SIG, (void**)ptr); } /*********************************************************************** * * PK11PrivKey.getPK11Token * * Figures out which slot this key lives on and wraps it in a PK11Token, * * RETURNS * NULL if an exception occurred, otherwise a new PK11Token object. */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11PrivKey_getOwningToken (JNIEnv *env, jobject this) { SECKEYPrivateKey *key = NULL; PK11SlotInfo *keySlot = NULL; jobject token = NULL; PR_ASSERT(env!=NULL && this!=NULL); /* Get the C key structure */ if( JSS_PK11_getPrivKeyPtr(env, this, &key) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } /* Get the slot that this key lives on */ keySlot = PK11_GetSlotFromPrivateKey(key); PR_ASSERT(keySlot != NULL); /* Turn the slot into a Java PK11Token */ token = JSS_PK11_wrapPK11Token(env, &keySlot); if(token == NULL) { PR_ASSERT( (*env)->ExceptionOccurred(env) ); goto finish; } finish: if(keySlot != NULL) { PK11_FreeSlot(keySlot); } return token; } /* * workaround for bug 100791: misspelled function prototypes in pk11func.h */ SECItem* PK11_GetLowLevelKeyIDForPrivateKey(SECKEYPrivateKey*); /********************************************************************** * PK11PrivKey.getUniqueID */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11PrivKey_getUniqueID (JNIEnv *env, jobject this) { SECKEYPrivateKey *key = NULL; SECItem *idItem = NULL; jbyteArray byteArray = NULL; PR_ASSERT(env!=NULL && this!=NULL); /*************************************************** * Get the private key structure ***************************************************/ if( JSS_PK11_getPrivKeyPtr(env, this, &key) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } /*************************************************** * Get the key id ***************************************************/ idItem = PK11_GetLowLevelKeyIDForPrivateKey(key); if(idItem == NULL ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to get key id"); goto finish; } /*************************************************** * Write the key id to a new byte array ***************************************************/ if (idItem->len > 0) { byteArray = JSS_ToByteArray(env, idItem->data, idItem->len); } finish: if (idItem != NULL) { SECITEM_FreeItem(idItem, PR_TRUE /*freeit*/); } return byteArray; } /********************************************************************** * PK11PrivKey.getStrength */ JNIEXPORT jint JNICALL Java_org_mozilla_jss_pkcs11_PK11PrivKey_getStrength (JNIEnv *env, jobject this) { SECKEYPrivateKey *key = NULL; PK11SlotInfo *slot = NULL; int strength; PR_ASSERT(env!=NULL && this!=NULL); /*************************************************** * Get the private key and slot C structures ***************************************************/ if( JSS_PK11_getPrivKeyPtr(env, this, &key) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); return -1; } slot = PK11_GetSlotFromPrivateKey(key); PR_ASSERT(slot!=NULL); /*************************************************** * Try to login to the token if necessary ***************************************************/ PK11_Authenticate(slot, PR_TRUE /*readCerts*/, NULL /*wincx*/); /*************************************************** * Get the strength ( in bytes ) ***************************************************/ strength = PK11_GetPrivateModulusLen(key); if( strength > 0 ) { /* convert to bits */ return strength * 8; } else { return strength; } } /*********************************************************************** * JSS_PK11_getKeyType * * Converts a PrivateKey.KeyType object to a PKCS #11 key type. * * INPUTS * keyTypeObj * A org.mozilla.jss.crypto.PrivateKey.KeyType object. * RETURNS * The key type, or nullKey if an exception occurred. */ KeyType JSS_PK11_getKeyType(JNIEnv *env, jobject keyTypeObj) { jclass keyTypeClass; jfieldID fieldID; char *fieldNames[] = { RSA_PRIVKEYTYPE_FIELD, DSA_PRIVKEYTYPE_FIELD, FORTEZZA_KEYTYPE_FIELD, DH_KEYTYPE_FIELD, KEA_KEYTYPE_FIELD, EC_KEYTYPE_FIELD }; int numTypes = 6; KeyType keyTypes[] = { rsaKey, dsaKey, fortezzaKey, dhKey, keaKey, ecKey }; jobject field; int i; PR_ASSERT(env!=NULL && keyTypeObj!=NULL); keyTypeClass = (*env)->FindClass(env, PRIVKEYTYPE_CLASS_NAME); if( keyTypeClass == NULL ) { PR_ASSERT( (*env)->ExceptionOccurred(env) ); goto finish; } for(i=0; i < numTypes; i++) { fieldID = (*env)->GetStaticFieldID(env, keyTypeClass, fieldNames[i], PRIVKEYTYPE_SIG); if( fieldID == NULL ) { PR_ASSERT( (*env)->ExceptionOccurred(env) ); goto finish; } field = (*env)->GetStaticObjectField(env, keyTypeClass, fieldID); if( field == NULL ) { PR_ASSERT( (*env)->ExceptionOccurred(env) ); goto finish; } if( (*env)->IsSameObject(env, keyTypeObj, field) ) { return keyTypes[i]; } } /* unrecognized type? */ PR_ASSERT( PR_FALSE ); finish: return nullKey; } /*********************************************************************** * importPrivateKey */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11PrivKey_fromPrivateKeyInfo ( JNIEnv *env, jclass clazz, jbyteArray keyArray, jobject tokenObj, jbyteArray publicValueArray ) { SECItem *derPK = NULL; jthrowable excep; SECStatus status; SECItem nickname; jobject keyObj = NULL; SECKEYPrivateKey* privk = NULL; PK11SlotInfo *slot = NULL; unsigned int keyUsage; SECItem *publicValue = NULL; PR_ASSERT(env!=NULL && clazz!=NULL); if(keyArray == NULL) { JSS_throw(env, NULL_POINTER_EXCEPTION); goto finish; } /* * copy the java byte arrays into local copies */ derPK = JSS_ByteArrayToSECItem(env, keyArray); if( derPK == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } if( publicValueArray != NULL ) { publicValue = JSS_ByteArrayToSECItem(env, publicValueArray); if( publicValue == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } } /* * get the slot */ if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } nickname.len = 0; nickname.data = NULL; /* * enable the key for as many operations as possible */ keyUsage = KU_ALL; status = PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, derPK, &nickname, publicValue, PR_FALSE /*isPerm*/, PR_TRUE /*isPrivate*/, keyUsage, &privk, NULL /*wincx*/); if(status != SECSuccess) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to import private key info"); goto finish; } PR_ASSERT(privk != NULL); keyObj = JSS_PK11_wrapPrivKey(env, &privk); finish: /* Save any exceptions */ if( (excep=(*env)->ExceptionOccurred(env)) != NULL ) { (*env)->ExceptionClear(env); } if( derPK != NULL ) { SECITEM_FreeItem(derPK, PR_TRUE /*freeit*/); } if( publicValue != NULL ) { SECITEM_FreeItem(publicValue, PR_TRUE /*freeit*/); } /* now re-throw the exception */ if( excep ) { (*env)->Throw(env, excep); } return keyObj; } #define ZERO_SECITEM(item) (item).data=NULL; (item).len=0; /*********************************************************************** * getDSAParamsNative * * Returns a 3-element array of byte[]. The elements are P, Q, and G. */ JNIEXPORT jobjectArray JNICALL Java_org_mozilla_jss_pkcs11_PK11PrivKey_getDSAParamsNative (JNIEnv *env, jobject this) { SECKEYPrivateKey *key = NULL; PQGParams *pqgParams = NULL; /*----PQG parameters and friends----*/ SECItem P; /* prime */ SECItem Q; /* subPrime */ SECItem G; /* base */ /*----Java versions of the PQG parameters----*/ jobject jP = NULL; jobject jQ = NULL; jobject jG = NULL; jobjectArray pqgArray = NULL; PR_ASSERT(env!=NULL && this!=NULL); /* clear the SECItems so we can free them indiscriminately at the end */ ZERO_SECITEM(P); ZERO_SECITEM(Q); ZERO_SECITEM(G); /* * Get the private key C structure */ if( JSS_PK11_getPrivKeyPtr(env, this, &key) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } /* * Get the PQG params from the private key */ pqgParams = (PQGParams*)PK11_GetPQGParamsFromPrivateKey(key); if( pqgParams == NULL ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to extract PQG parameters from private key"); goto finish; } if( PK11_PQG_GetPrimeFromParams( pqgParams, &P) || PK11_PQG_GetSubPrimeFromParams( pqgParams, &Q) || PK11_PQG_GetBaseFromParams( pqgParams, &G) ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to extract PQG parameters from private key"); goto finish; } /* * Now turn them into byte arrays */ if( !(jP = JSS_OctetStringToByteArray(env, &P)) || !(jQ = JSS_OctetStringToByteArray(env, &Q)) || !(jG = JSS_OctetStringToByteArray(env, &G)) ) { goto finish; } /* * Stash the byte arrays into an array of arrays. */ pqgArray = (*env)->NewObjectArray( env, 3, (*env)->GetObjectClass(env, jP), NULL); if( pqgArray == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } (*env)->SetObjectArrayElement(env, pqgArray, 0, jP); (*env)->SetObjectArrayElement(env, pqgArray, 1, jQ); (*env)->SetObjectArrayElement(env, pqgArray, 2, jG); finish: if(pqgParams!=NULL) { PK11_PQG_DestroyParams(pqgParams); } SECITEM_FreeItem(&P, PR_FALSE /*don't free P itself*/); SECITEM_FreeItem(&Q, PR_FALSE); SECITEM_FreeItem(&G, PR_FALSE); return pqgArray; } /********************************************************************** * PK11RSAPrivateKey.getModulusByteArray */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11RSAPrivateKey_getModulusByteArray (JNIEnv *env, jobject this) { SECKEYPrivateKey *privateKey = NULL; SECKEYPublicKey *publicKey = NULL; PK11SlotInfo *slot = NULL; int rv; jbyte *value = NULL; jint length; jbyteArray array = NULL; PR_ASSERT(env!=NULL && this!=NULL); // get private key rv = JSS_PK11_getPrivKeyPtr(env, this, &privateKey); // check return code if (rv != PR_SUCCESS) { char *message = PR_smprintf("Unable to get RSA private key (rc: %d)", rv); JSS_throwMsg(env, PK11_EXCEPTION, message); PR_smprintf_free(message); goto finish; } // get slot from private key slot = PK11_GetSlotFromPrivateKey(privateKey); PR_ASSERT(slot!=NULL); // login to token if necessary PK11_Authenticate(slot, PR_TRUE, NULL); // convert private key to public key publicKey = SECKEY_ConvertToPublicKey(privateKey); // get modulus from public key value = (jbyte*)publicKey->u.rsa.modulus.data; length = (jint)publicKey->u.rsa.modulus.len; // create byte array array = JSS_ToByteArray(env, value, length); // check byte array creation if (array == NULL) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } finish: if (publicKey) { SECKEY_DestroyPublicKey(publicKey); } if (slot) { PK11_FreeSlot(slot); } return array; } /********************************************************************** * PK11PrivKey.getPublicKey() * * Returns an instance of the public key from the private key. */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11PrivKey_getPublicKey (JNIEnv *env, jobject this) { SECKEYPrivateKey *privKey; SECKEYPublicKey *pubKey; if (JSS_PK11_getPrivKeyPtr(env, this, &privKey) != PR_SUCCESS) { JSS_throwMsg(env, NULL_POINTER_EXCEPTION, "Unable to get private " "key pointer from local instance"); return NULL; } pubKey = SECKEY_ConvertToPublicKey(privKey); if (pubKey == NULL) { JSS_throwMsgPrErr(env, NULL_POINTER_EXCEPTION, "Expected non-NULL " "private key to convert to non-NULL public key"); return NULL; } return JSS_PK11_wrapPubKey(env, &pubKey); } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11PrivKey.java000066400000000000000000000102171412550063600237420ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import java.math.BigInteger; import java.security.spec.DSAParameterSpec; import java.security.spec.PKCS8EncodedKeySpec; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.PrivateKey; import org.mozilla.jss.crypto.TokenException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class PK11PrivKey extends org.mozilla.jss.pkcs11.PK11Key implements PrivateKey { private static final long serialVersionUID = 1L; private PK11PrivKey() { } protected PK11PrivKey(byte[] pointer) { assert(pointer!=null); keyProxy = new PrivateKeyProxy(pointer); } /** * Make sure this key lives on the given token. */ public native void verifyKeyIsOnToken(PK11Token token) throws org.mozilla.jss.crypto.NoSuchItemOnTokenException; /** * Returns a new CryptoToken where this key resides. * * @return The PK11Token that owns this key. */ @Override public native CryptoToken getOwningToken(); @Override public native byte[] getUniqueID() throws TokenException; public native KeyType getKeyType(); @Override public PrivateKey.Type getType() { KeyType kt = getKeyType(); if( kt == KeyType.RSA ) { return PrivateKey.Type.RSA; } else if (kt == KeyType.DSA) { return PrivateKey.Type.DSA; } else { assert(kt == KeyType.EC); return PrivateKey.Type.EC; } } @Override public String getAlgorithm() { return getType().toString(); } /** * Returns the size in bits of the modulus of an RSA Private key. * Returns -1 for other types of keys. */ @Override public native int getStrength(); /** * Returns the corresponding public key from a private key instance. */ public native PK11PubKey getPublicKey(); /** * Imports a PrivateKeyInfo, storing it as a temporary PrivateKey * on the given token. * The key will be a temporary (session) key until it is imported * into a KeyStore, at which point it will be made a permanent (token) * object. */ public static PK11PrivKey fromPrivateKeyInfo(PKCS8EncodedKeySpec spec, CryptoToken token) throws TokenException { return fromPrivateKeyInfo(spec.getEncoded(), token); } /** * Imports a PrivateKeyInfo, storing it as a temporary PrivateKey * on the given token. * The key will be a temporary (session) key until it is imported * into a KeyStore, at which point it will be made a permanent (token) * object. */ public static PK11PrivKey fromPrivateKeyInfo(byte[] pki, CryptoToken token) throws TokenException { return fromPrivateKeyInfo(pki, token, null); } /** * Imports a PrivateKeyInfo, storing it as a temporary PrivateKey * on the given token. * The key will be a temporary (session) key until it is imported * into a KeyStore, at which point it will be made a permanent (token) * object. * @param publicValue An encoding of the public key, as used by the NSS * pk11wrap code. Don't use this unless you know what you're doing. */ public static native PK11PrivKey fromPrivateKeyInfo(byte[] pki, CryptoToken token, byte[] publicValue) throws TokenException; protected DSAParameterSpec getDSAParams() throws TokenException { byte[][] pqgArray = getDSAParamsNative(); return new DSAParameterSpec( new BigInteger(1, pqgArray[0]), new BigInteger(1, pqgArray[1]), new BigInteger(1, pqgArray[2]) ); } private native byte[][] getDSAParamsNative() throws TokenException; } class PrivateKeyProxy extends KeyProxy { public static Logger logger = LoggerFactory.getLogger(PrivateKeyProxy.class); public PrivateKeyProxy(byte[] pointer) { super(pointer); } @Override protected native void releaseNativeResources(); } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11PubKey.c000066400000000000000000000432051412550063600230540ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "_jni/org_mozilla_jss_pkcs11_PublicKeyProxy.h" #include "_jni/org_mozilla_jss_pkcs11_PK11RSAPublicKey.h" #include "_jni/org_mozilla_jss_pkcs11_PK11DSAPublicKey.h" #include "_jni/org_mozilla_jss_pkcs11_PK11ECPublicKey.h" #include #include #include #include #include #include #include #include #include #include "pk11util.h" #include "java_ids.h" #include #include /*********************************************************************** * PublicKeyProxy.releaseNativeResources */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PublicKeyProxy_releaseNativeResources (JNIEnv *env, jobject this) { SECKEYPublicKey *pubk; PRThread * VARIABLE_MAY_NOT_BE_USED pThread; PR_ASSERT(env!=NULL && this!=NULL); pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); PR_ASSERT(pThread != NULL); /* Get the SECKEYPublicKey structure */ if(JSS_getPtrFromProxy(env, this, (void**) &pubk) != PR_SUCCESS) { PR_ASSERT( PR_FALSE ); goto finish; } if (pubk != NULL) { SECKEY_DestroyPublicKey(pubk); } finish: PR_DetachThread(); return; } /*********************************************************************** ** JSS_PK11_wrapPubKey */ jobject JSS_PK11_wrapPubKey(JNIEnv *env, SECKEYPublicKey **pKey) { jobject pubKey=NULL; jclass keyClass; KeyType keyType; jmethodID constructor; jbyteArray ptr; char *keyClassName; PR_ASSERT(env!=NULL && pKey!=NULL); /* What kind of public key? */ keyType = (*pKey)->keyType; switch(keyType) { case rsaKey: keyClassName = PK11_RSA_PUBKEY_CLASS_NAME; break; case dsaKey: keyClassName = PK11_DSA_PUBKEY_CLASS_NAME; break; case ecKey: keyClassName = PK11_EC_PUBKEY_CLASS_NAME; break; default: keyClassName = PK11PUBKEY_CLASS_NAME; break; } keyClass = (*env)->FindClass(env, keyClassName); if(keyClass==NULL) { ASSERT_OUTOFMEM(env); goto finish; } constructor = (*env)->GetMethodID( env, keyClass, PK11PUBKEY_CONSTRUCTOR_NAME, PK11PUBKEY_CONSTRUCTOR_SIG); if(constructor == NULL) { ASSERT_OUTOFMEM(env); goto finish; } ptr = JSS_ptrToByteArray(env, (void*)*pKey); if(ptr == NULL) { ASSERT_OUTOFMEM(env); goto finish; } pubKey = (*env)->NewObject(env, keyClass, constructor, ptr); if(pubKey == NULL) { ASSERT_OUTOFMEM(env); goto finish; } *pKey = NULL; finish: if(pubKey==NULL && *pKey!=NULL) { SECKEY_DestroyPublicKey(*pKey); *pKey = NULL; } PR_DetachThread(); return pubKey; } /*********************************************************************** * Given a PublicKey object, extracts the SECKEYPublicKey* and stores it * at the given address. * * pubkObject: A JNI reference to a PublicKey object. * ptr: Address of a SECKEYPublicKey* that will receive the pointer. * Returns: PR_SUCCESS for success, PR_FAILURE if an exception was thrown. */ PRStatus JSS_PK11_getPubKeyPtr(JNIEnv *env, jobject pubkObject, SECKEYPublicKey** ptr) { PR_ASSERT(env!=NULL && pubkObject!=NULL); /* Get the pointer from the key proxy */ PR_ASSERT(sizeof(SECKEYPublicKey*) == sizeof(void*)); return JSS_getPtrFromProxyOwner(env, pubkObject, KEY_PROXY_FIELD, KEY_PROXY_SIG, (void**)ptr); } /*********************************************************************** * PK11PubKey.verifyKeyIsOnToken */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11PubKey_verifyKeyIsOnToken (JNIEnv *env, jobject this, jobject token) { PRThread * VARIABLE_MAY_NOT_BE_USED pThread; SECKEYPublicKey *key = NULL; PK11SlotInfo *slot = NULL; PK11SlotInfo *keySlot = NULL; PK11SlotInfo *internalSlot = NULL; pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); PR_ASSERT(pThread != NULL); if( JSS_PK11_getPubKeyPtr(env, this, &key) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } if( JSS_PK11_getTokenSlotPtr(env, token, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } internalSlot = PK11_GetInternalSlot(); #if 0 /* There is no way to extract a slot from a SECKEYPublicKey, except by * directly referencing the slot field. */ keySlot = PK11_GetSlotFromPublicKey(key); #else keySlot = PK11_ReferenceSlot(key->pkcs11Slot); #endif if (PK11_IsInternalKeySlot(keySlot)) { /* hack for internal module */ if (slot != keySlot && slot != internalSlot) { JSS_throwMsg(env, NO_SUCH_ITEM_ON_TOKEN_EXCEPTION, "Key is not present on this token"); goto finish; } } else if(keySlot != slot) { JSS_throwMsg(env, NO_SUCH_ITEM_ON_TOKEN_EXCEPTION, "Key is not present on this token"); goto finish; } finish: if (keySlot != NULL) { PK11_FreeSlot(keySlot); } if (internalSlot != NULL) { PK11_FreeSlot(internalSlot); } PR_DetachThread(); } /*********************************************************************** * PK11PubKey.getKeyType * * Returns: The KeyType of this key. */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11PubKey_getKeyType (JNIEnv *env, jobject this) { PRThread * VARIABLE_MAY_NOT_BE_USED pThread; SECKEYPublicKey *pubk; KeyType keyType; char* keyTypeFieldName; jclass keyTypeClass; jfieldID keyTypeField; jobject keyTypeObject = NULL; PR_ASSERT(env!=NULL && this!=NULL); pThread = PR_AttachThread(PR_SYSTEM_THREAD, 0, NULL); PR_ASSERT(pThread != NULL); if(JSS_PK11_getPubKeyPtr(env, this, &pubk) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL ); goto finish; } PR_ASSERT(pubk!=NULL); keyType = pubk->keyType; switch(keyType) { case nullKey: keyTypeFieldName = NULL_KEYTYPE_FIELD; break; case rsaKey: keyTypeFieldName = RSA_KEYTYPE_FIELD; break; case dsaKey: keyTypeFieldName = DSA_KEYTYPE_FIELD; break; case ecKey: keyTypeFieldName = EC_KEYTYPE_FIELD; break; case fortezzaKey: keyTypeFieldName = FORTEZZA_KEYTYPE_FIELD; break; case dhKey: keyTypeFieldName = DH_KEYTYPE_FIELD; break; case keaKey: keyTypeFieldName = KEA_KEYTYPE_FIELD; break; default: PR_ASSERT(PR_FALSE); keyTypeFieldName = NULL_KEYTYPE_FIELD; break; } keyTypeClass = (*env)->FindClass(env, KEYTYPE_CLASS_NAME); if(keyTypeClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } keyTypeField = (*env)->GetStaticFieldID(env, keyTypeClass, keyTypeFieldName, KEYTYPE_FIELD_SIG); if(keyTypeField==NULL) { ASSERT_OUTOFMEM(env); goto finish; } keyTypeObject = (*env)->GetStaticObjectField( env, keyTypeClass, keyTypeField); if(keyTypeObject == NULL) { ASSERT_OUTOFMEM(env); goto finish; } finish: PR_DetachThread(); return keyTypeObject; } typedef enum { DSA_P, DSA_Q, DSA_G, DSA_PUBLIC, RSA_MODULUS, RSA_PUBLIC_EXPONENT, EC_CURVE, EC_W } PublicKeyField; static jbyteArray get_public_key_info(JNIEnv *env, jobject this, PublicKeyField field); /********************************************************************** * * PK11RSAPublicKey.getModulusByteArray * * Returns the modulus of this RSA Public Key. The format is a big-endian * octet string in a byte array, suitable for importing into a BigInteger. * */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11RSAPublicKey_getModulusByteArray (JNIEnv *env, jobject this) { return get_public_key_info(env, this, RSA_MODULUS); } /********************************************************************** * * PK11RSAPublicKey.getPublicExponentByteArray * * Returns the modulus of this RSA Public Key. The format is a big-endian * octet string in a byte array, suitable for importing into a BigInteger. * */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11RSAPublicKey_getPublicExponentByteArray (JNIEnv *env, jobject this) { return get_public_key_info(env, this, RSA_PUBLIC_EXPONENT); } /********************************************************************** * * PK11DSAPublicKey.getPByteArray * * Returns the prime of this DSA Public Key. The format is a big-endian * octet string in a byte array, suitable for importing into a BigInteger. * */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11DSAPublicKey_getPByteArray (JNIEnv *env, jobject this) { return get_public_key_info(env, this, DSA_P); } /********************************************************************** * * PK11DSAPublicKey.getQByteArray * * Returns the subprime of this DSA Public Key. The format is a big-endian * octet string in a byte array, suitable for importing into a BigInteger. * */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11DSAPublicKey_getQByteArray (JNIEnv *env, jobject this) { return get_public_key_info(env, this, DSA_Q); } /********************************************************************** * * PK11DSAPublicKey.getGByteArray * * Returns the base of this DSA Public Key. The format is a big-endian * octet string in a byte array, suitable for importing into a BigInteger. * */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11DSAPublicKey_getGByteArray (JNIEnv *env, jobject this) { return get_public_key_info(env, this, DSA_G); } /********************************************************************** * * PK11DSAPublicKey.getYByteArray * * Returns the public value (Y) of this DSA Public Key. The format is a * big-endian octet string in a byte array, suitable for importing into * a BigInteger. * */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11DSAPublicKey_getYByteArray (JNIEnv *env, jobject this) { return get_public_key_info(env, this, DSA_PUBLIC); } /********************************************************************** * * PK11ECPublicKey.getParamByteArray * * Returns the curve of this EC Public Key. The format is a DER encoded * octet string in a byte array. * */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11ECPublicKey_getCurveByteArray (JNIEnv *env, jobject this) { return get_public_key_info(env, this, EC_CURVE); } /********************************************************************** * * PK11ECPublicKey.getWByteArray * * Returns the public value (W) of this EC Public Key. * The format is a 1 byte to indicate compression followed by points * Wx and Wy unsigned and concatenated. * */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11ECPublicKey_getWByteArray (JNIEnv *env, jobject this) { return get_public_key_info(env, this, EC_W); } /********************************************************************** * g e t _ p u b l i c _ k e y _ i n f o * * Looks up a field in a PK11PubKey and converts it to a Java byte array. * The field is assumed to be a SECItem big-endian octet string. The byte * array is suitable for feeding to a BigInteger constructor. */ static jbyteArray get_public_key_info (JNIEnv *env, jobject this, PublicKeyField field) { SECKEYPublicKey *pubk; jbyteArray byteArray=NULL; SECItem *item=NULL; PR_ASSERT(env!=NULL && this!=NULL); if( JSS_PK11_getPubKeyPtr(env, this, &pubk) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) ); goto finish; } switch( field ) { case DSA_P: PR_ASSERT(pubk->keyType == dsaKey); item = &pubk->u.dsa.params.prime; break; case DSA_Q: PR_ASSERT(pubk->keyType == dsaKey); item = &pubk->u.dsa.params.subPrime; break; case DSA_G: PR_ASSERT(pubk->keyType == dsaKey); item = &pubk->u.dsa.params.base; break; case DSA_PUBLIC: PR_ASSERT(pubk->keyType == dsaKey); item = &pubk->u.dsa.publicValue; break; case RSA_MODULUS: PR_ASSERT(pubk->keyType == rsaKey); item = &pubk->u.rsa.modulus; break; case RSA_PUBLIC_EXPONENT: PR_ASSERT(pubk->keyType == rsaKey); item = &pubk->u.rsa.publicExponent; break; case EC_CURVE: PR_ASSERT(pubk->keyType == ecKey); item = &pubk->u.ec.DEREncodedParams; break; case EC_W: PR_ASSERT(pubk->keyType == ecKey); item = &pubk->u.ec.publicValue; break; default: PR_ASSERT(PR_FALSE); break; } PR_ASSERT(item != NULL); byteArray = JSS_OctetStringToByteArray(env, item); if(byteArray == NULL) { PR_ASSERT( (*env)->ExceptionOccurred(env) ); goto finish; } finish: return byteArray; } /*********************************************************************** * * p u b k F r o m R a w * * Creates a PK11PubKey from its raw form. The raw form is a DER encoding * of the public key. For example, this is what is stored in a * SubjectPublicKeyInfo. */ static jobject pubkFromRaw(JNIEnv *env, CK_KEY_TYPE type, jbyteArray rawBA) { jobject pubkObj=NULL; SECKEYPublicKey *pubk=NULL; SECItem *pubkDER=NULL; /* validate args */ PR_ASSERT(env!=NULL); if( rawBA == NULL ) { JSS_throw(env, NULL_POINTER_EXCEPTION); goto finish; } pubkDER = JSS_ByteArrayToSECItem(env, rawBA); if( pubkDER == NULL ) { /* exception was thrown */ goto finish; } pubk = SECKEY_ImportDERPublicKey(pubkDER, type); if( pubk == NULL ) { JSS_throw(env, INVALID_KEY_FORMAT_EXCEPTION); goto finish; } /* this clears pubk */ pubkObj = JSS_PK11_wrapPubKey(env, &pubk); if( pubkObj == NULL ) { /* exception was thrown */ goto finish; } finish: if(pubkDER!=NULL) { SECITEM_FreeItem(pubkDER, PR_TRUE /*freeit*/); } return pubkObj; } /*********************************************************************** * * PK11PubKey.fromRawNative */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11PubKey_fromRawNative (JNIEnv *env, jclass clazz, jint type, jbyteArray rawBA) { return pubkFromRaw(env, type, rawBA); } /*********************************************************************** * * PK11PubKey.RSAfromRaw * Deprecated: call fromRawNative instead. */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11PubKey_RSAFromRaw (JNIEnv *env, jclass clazz, jbyteArray rawBA) { return pubkFromRaw(env, CKK_RSA, rawBA); } /*********************************************************************** * * PK11PubKey.DSAfromRaw * Deprecated: call fromRawNative instead. */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11PubKey_DSAFromRaw (JNIEnv *env, jclass clazz, jbyteArray rawBA) { return pubkFromRaw(env, CKK_DSA, rawBA); } /*********************************************************************** * * PK11PubKey.getEncoded * * Converts the public key to a SubjectPublicKeyInfo, and returns its * DER-encoding. */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11PubKey_getEncoded (JNIEnv *env, jobject this) { SECKEYPublicKey *pubk; jbyteArray encodedBA=NULL; SECItem *spkiDER=NULL; /* get the public key */ if( JSS_PK11_getPubKeyPtr(env, this, &pubk) != PR_SUCCESS ) { /* exception was thrown */ goto finish; } spkiDER = PK11_DEREncodePublicKey(pubk); if( spkiDER == NULL ) { JSS_trace(env, JSS_TRACE_ERROR, "unable to DER-encode" " SubjectPublicKeyInfo"); JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } /* convert the der-encoding to a Java byte array */ encodedBA = JSS_SECItemToByteArray(env, spkiDER); finish: if(spkiDER!=NULL) { SECITEM_FreeItem(spkiDER, PR_TRUE /*freeit*/); } return encodedBA; } /*********************************************************************** * * PK11PubKey.fromSPKI * * Generates a PK11PubKey from a DER-encoded SubjectPublicKeyInfo. */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11PubKey_fromSPKI (JNIEnv *env, jobject this, jbyteArray spkiBA) { jobject pubkObj = NULL; SECItem *spkiItem = NULL; CERTSubjectPublicKeyInfo *spki = NULL; SECKEYPublicKey *pubk = NULL; /* * convert byte array to SECItem */ spkiItem = JSS_ByteArrayToSECItem(env, spkiBA); if( spkiItem == NULL ) { /* exception was thrown */ goto finish; } /* * convert SECItem to SECKEYPublicKey */ spki = SECKEY_DecodeDERSubjectPublicKeyInfo(spkiItem); if( spki == NULL ) { JSS_throwMsg(env, INVALID_KEY_FORMAT_EXCEPTION, "Unable to decode DER-encoded SubjectPublicKeyInfo: " "invalid DER encoding"); goto finish; } pubk = SECKEY_ExtractPublicKey(spki); if( pubk == NULL ) { JSS_throwMsg(env, INVALID_KEY_FORMAT_EXCEPTION, "Unable to decode SubjectPublicKeyInfo: DER encoding problem, or" " unrecognized key type "); goto finish; } /* * put a Java wrapper around it */ pubkObj = JSS_PK11_wrapPubKey(env, &pubk); /* this clears pubk */ if( pubkObj == NULL ) { /* exception was thrown */ goto finish; } finish: if( spkiItem != NULL ) { SECITEM_FreeItem(spkiItem, PR_TRUE /*freeit*/); } if( spki != NULL ) { SECKEY_DestroySubjectPublicKeyInfo(spki); } if( pubk != NULL ) { SECKEY_DestroyPublicKey(pubk); } return pubkObj; } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11PubKey.java000066400000000000000000000064401412550063600235530ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import org.mozilla.jss.crypto.InvalidKeyFormatException; import org.mozilla.jss.crypto.PrivateKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class PK11PubKey extends org.mozilla.jss.pkcs11.PK11Key implements java.security.PublicKey { private static final long serialVersionUID = 1L; protected PK11PubKey(byte[] pointer) { assert(pointer!=null); keyProxy = new PublicKeyProxy(pointer); } /** * Make sure this key lives on the given token. */ public native void verifyKeyIsOnToken(PK11Token token) throws org.mozilla.jss.crypto.NoSuchItemOnTokenException; public native KeyType getKeyType(); @Override public String getAlgorithm() { return getKeyType().toString(); } /** * Creates a PK11PubKey from its raw form. The raw form is a DER encoding * of the public key. For example, this is what is stored in a * SubjectPublicKeyInfo. * * @param type The type of private key to be decoded. * @param rawKey The bytes of the raw key. * @exception InvalidKeyFormatException If the raw key could not be * decoded. * @deprecated This method works for RSA keys but not DSA or EC keys. Use * fromSPKI() instead. * @see #fromSPKI(byte[]) */ @Deprecated public static PK11PubKey fromRaw(PrivateKey.Type type, byte[] rawKey) throws InvalidKeyFormatException { if( type != PrivateKey.Type.RSA ) { throw new InvalidKeyFormatException( "fromRaw() is broken for DSA keys. Use fromSPKI() instead."); } return fromRawNative( type.getPKCS11Type(), rawKey ); } /** * param type The PKCS #11 type of the key (CKK_). */ private static native PK11PubKey fromRawNative(int type, byte[] rawKey) throws InvalidKeyFormatException; /** * Creates a PK11PubKey from a SubjectPublicKeyInfo. * * @param spki The BER-encoded SubjectPublicKeyInfo. * @exception InvalidKeyFormatException If the SPKI could not be * decoded. */ public static native PK11PubKey fromSPKI(byte[] spki) throws InvalidKeyFormatException; /** * deprecated Use fromRawNative instead. */ private static native PK11PubKey RSAFromRaw(byte[] rawKey); /** * deprecated Use fromRawNative instead. */ private static native PK11PubKey DSAFromRaw(byte[] rawKey); /** * Returns a DER-encoded SubjectPublicKeyInfo representing this key. */ @Override public native byte[] getEncoded(); /** * The name of the primary encoding format of this key. The primary * encoding format is X.509 SubjectPublicKeyInfo, and the name * is "X.509". */ @Override public String getFormat() { return "X.509"; } } class PublicKeyProxy extends KeyProxy { public static Logger logger = LoggerFactory.getLogger(PublicKeyProxy.class); public PublicKeyProxy(byte[] pointer) { super(pointer); } @Override protected native void releaseNativeResources(); } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11RSAPrivateKey.java000066400000000000000000000016441412550063600250060ustar00rootroot00000000000000package org.mozilla.jss.pkcs11; import java.math.BigInteger; import org.mozilla.jss.crypto.PrivateKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class PK11RSAPrivateKey extends PK11PrivKey implements java.security.interfaces.RSAKey { public static Logger logger = LoggerFactory.getLogger(PK11RSAPrivateKey.class); private static final long serialVersionUID = 1L; private PK11RSAPrivateKey() { super(null); } protected PK11RSAPrivateKey(byte[] pointer) { super(pointer); } @Override public PrivateKey.Type getType() { return PrivateKey.Type.RSA; } @Override public BigInteger getModulus() { logger.debug("PK11RSAPrivateKey: getModulus()"); return new BigInteger(1, getModulusByteArray()); } native byte[] getModulusByteArray(); public BigInteger getPrivateExponent() { // !!! return null; } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11RSAPublicKey.java000066400000000000000000000020211412550063600246000ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import java.security.interfaces.RSAPublicKey; import java.math.BigInteger; public class PK11RSAPublicKey extends PK11PubKey implements RSAPublicKey { private static final long serialVersionUID = 1L; public PK11RSAPublicKey(byte[] pointer) { super(pointer); } @Override public BigInteger getModulus() { try { return new BigInteger(1, getModulusByteArray()); } catch( NumberFormatException e) { return null; } } private native byte[] getModulusByteArray(); @Override public BigInteger getPublicExponent() { try { return new BigInteger(1, getPublicExponentByteArray()); } catch( NumberFormatException e) { return null; } } private native byte[] getPublicExponentByteArray(); } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11SecureRandom.c000066400000000000000000000116441412550063600242460ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * NSS and NSPR header files */ #include #include /* * JNI header files */ #include "_jni/org_mozilla_jss_pkcs11_PK11SecureRandom.h" /* * JSS header files */ #include /* * JNI FUNCTION: PK11SecureRandom.setSeed * * JNI FUNCTION TYPE: protected * * JNI INPUTS: * * env * The JNI object through which all JNI functions are referenced * * this * A JNI reference to the class which defines this native method * * INPUTS: * * N/A * * OUTPUTS: * * jseed * A JNI array for storage of the random byte seed sequence * * ERRORS: * * N/A * * RETURN: * * Upon success, this method returns a byte array * containing a random byte sequence * * NOTES: * * This routine is called to seed the pseudo-random number generator. * * JNI NOTES: * * Class: org_mozilla_jss_pkcs11_PK11SecureRandom * Method: setSeed * Signature: ([B)V */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11SecureRandom_setSeed ( JNIEnv* env, jobject this, jbyteArray jseed ) { /* * "JNI" data members */ jbyte* jdata = NULL; jsize jlen = 0; /* * "C" data members */ PRThread* VARIABLE_MAY_NOT_BE_USED pThread = NULL; SECStatus status = PR_FALSE; PK11SlotInfo* slot = NULL; /* * Perform initial assertions */ PR_ASSERT( env != NULL && this != NULL ); /* * Attach to the external java thread */ pThread = PR_AttachThread( PR_SYSTEM_THREAD, 0, NULL ); PR_ASSERT( pThread != NULL ); /* * Obtain the appropriate "slot" */ slot = PK11_GetBestSlot( CKM_FAKE_RANDOM, NULL ); if( slot == NULL ) { PR_ASSERT( PR_FALSE ); goto finish; } /* * Convert "JNI jbyteArray" into "JNI jbyte*" so * that it can be cast into a "C unsigned char*"; * also get its length. */ JSS_RefByteArray(env, jseed, &jdata, &jlen); /* * Seed the pseudo-random number generator; * currently, failures from this routine are ignored */ status = PK11_SeedRandom( slot, ( unsigned char* ) jdata, ( int ) jlen ); if( status != SECSuccess ) { PR_ASSERT( PR_FALSE ); goto finish; } finish: /* * Copy back the contents of the "JNI jbyte*" and * free any resources associated with it */ JSS_DerefByteArray(env, jseed, jdata, 0); /* * Free any "C" resources */ if( slot != NULL ) { PK11_FreeSlot( slot ); } slot = NULL; /* * Detach from the external java thread and return */ PR_DetachThread(); return; } /* * JNI FUNCTION: PK11SecureRandom.nextBytes * * JNI FUNCTION TYPE: protected * * JNI INPUTS: * * env * The JNI object through which all JNI functions are referenced * * this * A JNI reference to the class which defines this native method * * INPUTS: * * N/A * * OUTPUTS: * * jbytes * A JNI array for storage of the random byte sequence * * ERRORS: * * N/A * * RETURN: * * Upon success, this method returns a byte array * containing a random byte sequence * * NOTES: * * This routine is called to generate a pseudo-random number. * * JNI NOTES: * * Class: org_mozilla_jss_pkcs11_PK11SecureRandom * Method: nextBytes * Signature: ([B)V */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11SecureRandom_nextBytes ( JNIEnv* env, jobject this, jbyteArray jbytes ) { /* * "JNI" data members */ jbyte* jdata = NULL; jsize jlen = 0; /* * "C" data members */ PRThread* VARIABLE_MAY_NOT_BE_USED pThread = NULL; SECStatus status = PR_FALSE; /* * Perform initial assertions */ PR_ASSERT( env != NULL && this != NULL ); /* * Attach to the external java thread */ pThread = PR_AttachThread( PR_SYSTEM_THREAD, 0, NULL ); PR_ASSERT( pThread != NULL ); /* * Convert "JNI jbyteArray" into "JNI jbyte*" so * that it can be cast into a "C unsigned char*"; * also get its length. */ JSS_RefByteArray(env, jbytes, &jdata, &jlen); /* * Generate a pseudo-random number; currently, * failures from this routine are ignored */ status = PK11_GenerateRandom( ( unsigned char* ) jdata, ( int ) jlen ); if( status != SECSuccess ) { goto finish; } finish: /* * Copy back the contents of the "JNI jbyte*" and * free any resources associated with it */ JSS_DerefByteArray(env, jbytes, jdata, 0); /* * Detach from the external java thread and return */ PR_DetachThread(); return; } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11SecureRandom.java000066400000000000000000000022501412550063600247360ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; /** * A random number generator for PKCS #11. * * @see org.mozilla.jss.CryptoManager */ public final class PK11SecureRandom implements org.mozilla.jss.crypto.JSSSecureRandom { //////////////////////////////////////////////////// // construction and finalization //////////////////////////////////////////////////// public PK11SecureRandom() {} //////////////////////////////////////////////////// // public routines //////////////////////////////////////////////////// @Override public synchronized native void setSeed( byte[] seed ); @Override public void setSeed( long seed ) { byte[] data = new byte[8]; // convert long into 8-byte byte array for( int i = 0; i < 8; i++ ) { data[i] = ( byte ) ( seed >> ( 8 * i ) ); } setSeed( data ); } @Override public synchronized native void nextBytes( byte bytes[] ); } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11Signature.c000066400000000000000000000616671412550063600236320ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include "_jni/org_mozilla_jss_pkcs11_PK11Signature.h" #include "_jni/org_mozilla_jss_pkcs11_SigContextProxy.h" #include #include #include #include #include #include #include #include #include "pk11util.h" static PRStatus getPrivateKey(JNIEnv *env, jobject sig, SECKEYPrivateKey**key); static PRStatus getPublicKey(JNIEnv *env, jobject sig, SECKEYPublicKey**key); static PRStatus getSomeKey(JNIEnv *env, jobject sig, void **key, short type); static SECOidTag getAlgorithm(JNIEnv *env, jobject sig); static SECOidTag getDigestAlgorithm(JNIEnv *env, jobject sig); static void setSigContext(JNIEnv *env, jobject sig, jobject context); static PRStatus getSigContext(JNIEnv *env, jobject sig, void**pContext, SigContextType* pType); static SECStatus getRSAPSSParamsAndSigningAlg(JNIEnv *env, jobject this, PRArenaPool *arena, SECAlgorithmID **alg, SECKEYPrivateKey *privk); /*********************************************************************** * * PK11Signature.initSigContext */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11Signature_initSigContext (JNIEnv *env, jobject this) { SGNContext *ctxt = NULL; jobject contextProxy = NULL; SECKEYPrivateKey *privk = NULL; SECAlgorithmID *signAlg = NULL; SECStatus rv = SECFailure; PRArenaPool *arena = NULL; SECOidTag signingAlg = SEC_OID_UNKNOWN; /* Extract the private key from the PK11Signature */ if (getPrivateKey(env, this, &privk) != PR_SUCCESS) { PR_ASSERT((*env)->ExceptionOccurred(env) != NULL); goto finish; } signingAlg = getAlgorithm(env,this); if (signingAlg == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) { arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (!arena) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } rv = getRSAPSSParamsAndSigningAlg(env, this, arena, &signAlg, privk); if (rv == SECFailure) { goto finish; } /* Start the signing operation */ ctxt = SGN_NewContextWithAlgorithmID(signAlg, privk); } else { ctxt = SGN_NewContext(signingAlg, privk); } if (ctxt == NULL) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Unable to create signing context"); goto finish; } if (SGN_Begin(ctxt) != SECSuccess) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Unable to begin signing context"); goto finish; } /* Create a contextProxy and stick it in the PK11Signature object */ contextProxy = JSS_PK11_wrapSigContextProxy(env, (void**)&ctxt, SGN_CONTEXT, &arena); if (contextProxy == NULL) { PR_ASSERT((*env)->ExceptionOccurred(env) != NULL); goto finish; } // Signature algorithm for RSA PSS allocated in the arena, // which is destroyed on exit. setSigContext(env, this, contextProxy); finish: if (contextProxy == NULL && ctxt != NULL) { /* we created a context but not the Java wrapper, so we need to * delete the context here. */ SGN_DestroyContext(ctxt, PR_TRUE /*freeit*/); } /* When contentProxy is created, arena will be NULLed and contentProxy * takes ownership of it. Otherwise, when arena still exists, we must * free it now. */ PORT_FreeArena(arena, PR_TRUE /* zero */); } JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11Signature_initVfyContext (JNIEnv *env, jobject this) { VFYContext *ctxt = NULL; jobject contextProxy = NULL; SECKEYPublicKey *pubk = NULL; SECKEYPrivateKey *privk = NULL; SECKEYPublicKey *tempPubKey = NULL; PRArenaPool *arena = NULL; SECAlgorithmID *signAlg = NULL; SECStatus rv = SECFailure; SECOidTag signingAlg = SEC_OID_UNKNOWN; if (getPublicKey(env, this, &pubk) != PR_SUCCESS) { PR_ASSERT((*env)->ExceptionOccurred(env) != NULL); goto finish; } signingAlg = getAlgorithm(env,this); if (signingAlg == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) { /* Create place holder private key, just to create the PSS Params. */ unsigned key_bits = SECKEY_PublicKeyStrengthInBits(pubk); privk = SECKEY_CreateRSAPrivateKey(key_bits, &tempPubKey, NULL); if (privk == NULL) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Unable to create temporary RSA key"); goto finish; } arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } rv = getRSAPSSParamsAndSigningAlg(env, this, arena, &signAlg, privk); if (rv == SECFailure) { PR_ASSERT((*env)->ExceptionOccurred(env) != NULL); goto finish; } SECOidTag digestAlg = SEC_OID_UNKNOWN; digestAlg = getDigestAlgorithm(env, this); ctxt = VFY_CreateContextWithAlgorithmID(pubk, NULL, signAlg, &digestAlg, NULL); } else { ctxt = VFY_CreateContext(pubk, NULL /*sig*/, signingAlg, NULL /*wincx*/); } if (ctxt == NULL) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Unable to create vfy context"); goto finish; } if (VFY_Begin(ctxt) != SECSuccess) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Unable to begin verification context"); goto finish; } /* create a ContextProxy and stick it in the PK11Signature object */ contextProxy = JSS_PK11_wrapSigContextProxy(env, (void**)&ctxt, VFY_CONTEXT, &arena); if (contextProxy == NULL) { PR_ASSERT((*env)->ExceptionOccurred(env) != NULL); goto finish; } setSigContext(env, this, contextProxy); finish: if (contextProxy == NULL && ctxt != NULL) { /* we created a context but not the Java wrapper, so we need to * delete the context here */ VFY_DestroyContext(ctxt, PR_TRUE /*freeit*/); } SECKEY_DestroyPublicKey(tempPubKey); SECKEY_DestroyPrivateKey(privk); /* When contentProxy is created, arena will be NULLed and contentProxy * takes ownership of it. Otherwise, when arena still exists, we must * free it now. */ PORT_FreeArena(arena, PR_TRUE /* zero */); } /********************************************************************** * * PK11Signature.engineUpdateNative * */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11Signature_engineUpdateNative (JNIEnv *env, jobject this, jbyteArray bArray, jint offset, jint length) { SigContextType type; void *ctxt; jbyte *bytes=NULL; jint numBytes; /* Extract the signature context */ if( getSigContext(env, this, &ctxt, &type) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } PR_ASSERT(ctxt != NULL); /* Get the bytes to be updated */ if (!JSS_RefByteArray(env, bArray, &bytes, &numBytes)) { ASSERT_OUTOFMEM(env); goto finish; } if( offset < 0 || offset >= numBytes || length < 0 || (offset+length) > numBytes || (offset+length) < 0 ) { JSS_throw(env, ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION); goto finish; } /* Update the context */ if(type == SGN_CONTEXT) { if( SGN_Update( (SGNContext*)ctxt, (unsigned char*)bytes + offset, (unsigned)length ) != SECSuccess) { JSS_throwMsgPrErr(env, SIGNATURE_EXCEPTION, "update failed"); goto finish; } } else { PR_ASSERT( type == VFY_CONTEXT ); if( VFY_Update( (VFYContext*)ctxt, (unsigned char*)bytes + offset, (unsigned) length ) != SECSuccess) { JSS_throwMsgPrErr(env, SIGNATURE_EXCEPTION, "update failed"); goto finish; } } finish: JSS_DerefByteArray(env, bArray, bytes, JNI_ABORT); } /********************************************************************** * * PK11Signature.engineSignNative * */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11Signature_engineSignNative (JNIEnv *env, jobject this) { SGNContext *ctxt; SigContextType type; SECItem signature; jbyteArray sigArray=NULL; PR_ASSERT(env!=NULL && this!=NULL); signature.data = NULL; /* * Extract the signature context from the Java wrapper */ if( getSigContext(env, this, (void**)&ctxt, &type) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } PR_ASSERT(ctxt!=NULL && type==SGN_CONTEXT); /* * Finish the signing operation. */ if( SGN_End(ctxt, &signature) != SECSuccess) { JSS_throwMsgPrErr(env, SIGNATURE_EXCEPTION, "Signing operation failed"); goto finish; } /* * Convert SECItem signature to Java byte array */ sigArray = JSS_ToByteArray(env, signature.data, signature.len); if (sigArray == NULL) { ASSERT_OUTOFMEM(env); goto finish; } finish: if( signature.data != NULL ) { PR_Free(signature.data); } return sigArray; } JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_pkcs11_PK11Signature_engineVerifyNative (JNIEnv *env, jobject this, jbyteArray sigArray) { jboolean verified = JNI_FALSE; VFYContext *ctxt; SigContextType type; SECItem sigItem = {siBuffer, NULL, 0}; PR_ASSERT( env!=NULL && this!=NULL && sigArray!=NULL); /* * Lookup the context */ if( getSigContext(env, this, (void**)&ctxt, &type) != PR_SUCCESS) { PR_ASSERT(PR_FALSE); JSS_throwMsgPrErr(env, SIGNATURE_EXCEPTION, "Unable to retrieve verification context"); goto finish; } if(type != VFY_CONTEXT) { PR_ASSERT(PR_FALSE); JSS_throwMsgPrErr(env, SIGNATURE_EXCEPTION, "Verification engine has signature context"); goto finish; } /* * Convert signature to SECItem */ if (!JSS_RefByteArray(env, sigArray, (jbyte **) &sigItem.data, (jsize *) &sigItem.len)) { ASSERT_OUTOFMEM(env); goto finish; } /* * Finish the verification operation */ if( VFY_EndWithSignature(ctxt, &sigItem) == SECSuccess) { verified = JNI_TRUE; } else if( PR_GetError() != SEC_ERROR_BAD_SIGNATURE) { PR_ASSERT(PR_FALSE); JSS_throwMsgPrErr(env, SIGNATURE_EXCEPTION, "Failed to complete verification operation"); goto finish; } finish: JSS_DerefByteArray(env, sigArray, sigItem.data, JNI_ABORT); return verified; } /* * Extract the algorithm from a PK11Signature. * * sig: a PK11Signature. * Returns: the algorithm of this signature, or SEC_OID_UNKNOWN if an * error occurs. */ static SECOidTag getAlgorithm(JNIEnv *env, jobject sig) { jclass sigClass; jfieldID algField; jobject alg; PR_ASSERT(env != NULL && sig != NULL); sigClass = (*env)->GetObjectClass(env, sig); if (sigClass == NULL) { ASSERT_OUTOFMEM(env); return SEC_OID_UNKNOWN; } algField = (*env)->GetFieldID(env, sigClass, SIG_ALGORITHM_FIELD, SIG_ALGORITHM_SIG); if (algField == NULL) { ASSERT_OUTOFMEM(env); return SEC_OID_UNKNOWN; } alg = (*env)->GetObjectField(env, sig, algField); if (alg == NULL) { ASSERT_OUTOFMEM(env); return SEC_OID_UNKNOWN; } return JSS_getOidTagFromAlg(env, alg); } static SECOidTag getDigestAlgorithm(JNIEnv *env, jobject sig) { jclass sigClass; jfieldID algField; jobject alg; PR_ASSERT(env != NULL && sig != NULL); sigClass = (*env)->GetObjectClass(env, sig); if (sigClass == NULL) { ASSERT_OUTOFMEM(env); return SEC_OID_UNKNOWN; } algField = (*env)->GetFieldID(env, sigClass, SIG_DIGEST_ALGORITHM_FIELD, SIG_ALGORITHM_SIG); if (algField == NULL) { ASSERT_OUTOFMEM(env); return SEC_OID_UNKNOWN; } alg = (*env)->GetObjectField(env, sig, algField); if (alg == NULL) { /* Do not ASSERT_OUTOFMEM: it is possible for digestAlgorithm to be * NULL in sig and thus alg will be NULL here; no exception will be * raised. */ return SEC_OID_UNKNOWN; } return JSS_getOidTagFromAlg(env, alg); } static SECStatus getRSAPSSParamsAndSigningAlg(JNIEnv *env, jobject this, PRArenaPool *arena, SECAlgorithmID **alg, SECKEYPrivateKey *privk) { SECItem *sigAlgParams = NULL; SECAlgorithmID *signAlg = NULL; SECOidTag digestAlg = SEC_OID_UNKNOWN; SECStatus rv = SECFailure; if (alg == NULL) { return rv; } signAlg = (SECAlgorithmID *)PORT_ArenaZAlloc(arena, sizeof(SECAlgorithmID)); if (signAlg == NULL) { JSS_throw(env, OUT_OF_MEMORY_ERROR); return rv; } digestAlg = getDigestAlgorithm(env, this); sigAlgParams = SEC_CreateSignatureAlgorithmParameters(arena, NULL, SEC_OID_PKCS1_RSA_PSS_SIGNATURE, digestAlg, NULL, privk); if (sigAlgParams == NULL) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Unable to create signature algorithm parameters"); return rv; } *alg = signAlg; rv = SECOID_SetAlgorithmID(arena, *alg, SEC_OID_PKCS1_RSA_PSS_SIGNATURE, sigAlgParams); if (rv != SECSuccess) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Unable to set RSA-PSS Algorithm ID"); } return rv; } /* * Set the contextProxy member of a PK11Signature. * * sig: the PK11Signature whose contextProxy we are setting. * context: the ContextProxy we are setting in the signature. It may be NULL. **/ static void setSigContext(JNIEnv *env, jobject sig, jobject context) { jclass sigClass; jfieldID contextField; PR_ASSERT(env!=NULL && sig!=NULL); sigClass = (*env)->GetObjectClass(env, sig); PR_ASSERT(sigClass!=NULL); contextField = (*env)->GetFieldID( env, sigClass, SIG_CONTEXT_PROXY_FIELD, SIG_CONTEXT_PROXY_SIG); if(contextField == NULL) { ASSERT_OUTOFMEM(env); /* This function doesn't advertise that it can throw exceptions, * so we shouldn't throw one */ (*env)->ExceptionClear(env); return; } (*env)->SetObjectField(env, sig, contextField, context); } /* * Don't call this if there is no context. */ static PRStatus getSigContext(JNIEnv *env, jobject sig, void**pContext, SigContextType* pType) { jfieldID contextField; jclass sigClass; jobject proxy; PR_ASSERT(env!=NULL && sig!=NULL && pContext!=NULL && pType!=NULL); sigClass = (*env)->GetObjectClass(env, sig); #ifdef DEBUG { jclass realSigClass = (*env)->FindClass(env, PK11SIGNATURE_CLASS_NAME); PR_ASSERT( (*env)->IsInstanceOf(env, sig, realSigClass) ); } #endif contextField = (*env)->GetFieldID(env, sigClass, SIG_CONTEXT_PROXY_FIELD, SIG_CONTEXT_PROXY_SIG); if(contextField == NULL) { ASSERT_OUTOFMEM(env); return PR_FAILURE; } proxy = (*env)->GetObjectField(env, sig, contextField); if(proxy == NULL) { PR_ASSERT(PR_FALSE); JSS_throw(env, TOKEN_EXCEPTION); return PR_FAILURE; } if( JSS_PK11_getSigContext(env, proxy, pContext, pType) != PR_SUCCESS ) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); return PR_FAILURE; } PR_ASSERT(*pContext != NULL); return PR_SUCCESS; } #define PUBLICKEYTYPE 0 #define PRIVATEKEYTYPE 1 /********************************************************************** * * g e t P r i v a t e K e y */ static PRStatus getPrivateKey(JNIEnv *env, jobject sig, SECKEYPrivateKey**key) { return getSomeKey(env, sig, (void**)key, PRIVATEKEYTYPE); } /********************************************************************** * * g e t P u b l i c K e y */ static PRStatus getPublicKey(JNIEnv *env, jobject sig, SECKEYPublicKey**key) { return getSomeKey(env, sig, (void**)key, PUBLICKEYTYPE); } static PRStatus getSomeKey(JNIEnv *env, jobject sig, void **key, short type) { jfieldID keyField; jclass sigClass; jobject keyProxy; PR_ASSERT(env!=NULL && sig!=NULL && key!=NULL); sigClass = (*env)->GetObjectClass(env, sig); #ifdef DEBUG { jclass realSigClass = (*env)->FindClass(env, PK11SIGNATURE_CLASS_NAME); PR_ASSERT( (*env)->IsInstanceOf(env, sig, realSigClass) ); } #endif keyField = (*env)->GetFieldID(env, sigClass, SIG_KEY_FIELD, SIG_KEY_SIG); if(keyField == NULL) { ASSERT_OUTOFMEM(env); return PR_FAILURE; } keyProxy = (*env)->GetObjectField(env, sig, keyField); if(keyProxy == NULL) { PR_ASSERT(PR_FALSE); JSS_throw(env, TOKEN_EXCEPTION); return PR_FAILURE; } if(type == PRIVATEKEYTYPE) { if( JSS_PK11_getPrivKeyPtr(env, keyProxy, (SECKEYPrivateKey**)key) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); return PR_FAILURE; } } else { if( JSS_PK11_getPubKeyPtr(env, keyProxy, (SECKEYPublicKey**)key) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); return PR_FAILURE; } } PR_ASSERT(*key != NULL); return PR_SUCCESS; } struct SigContextProxyStr { void *ctxt; SigContextType type; PRArenaPool *arena; }; /*********************************************************************** * J S S _ P K 1 1 _ g e t S i g C o n t e x t * * Extracts the context pointer from a SigContextProxy. * proxy: a non-NULL SigContextProxy object. * pContext: address of a SGNContext* or VFYContext* where the pointer will be * stored. * pType: address of a SigContextType where will be stored the type * of the context either SGN_CONTEXT or VFY_CONTEXT. * Returns: PR_SUCCESS, unless an exception was thrown. */ PRStatus JSS_PK11_getSigContext(JNIEnv *env, jobject proxy, void**pContext, SigContextType *pType) { SigContextProxy *ctxtProxy; PR_ASSERT(env!=NULL && proxy!=NULL && pContext!=NULL && pType!=NULL); if( JSS_getPtrFromProxy(env, proxy, (void**)&ctxtProxy) != PR_SUCCESS) { ASSERT_OUTOFMEM(env); return PR_FAILURE; } /* Make sure the pointers are OK */ if(ctxtProxy==NULL || ctxtProxy->ctxt==NULL) { PR_ASSERT(PR_FALSE); JSS_throw(env, SIGNATURE_EXCEPTION); return PR_FAILURE; } /* Everything looks good, return the pointer */ *pContext = ctxtProxy->ctxt; *pType = ctxtProxy->type; return PR_SUCCESS; } /********************************************************************** * * J S S _ P K 1 1 _ w r a p S i g C o n t e x t P r o x y * * Wraps a SGNContext in a SigContextProxy. * * ctxt: address of ptr to a SGNContext or VfyContext, which must not be NULL. * It will be eaten by the wrapper and set to NULL. * * type: type of context, either SGN_CONTEXT or VFY_CONTEXT * Returns: a new SigContextProxy object wrapping the given SGNContext, or * NULL if an exception was thrown. */ jobject JSS_PK11_wrapSigContextProxy(JNIEnv *env, void **ctxt, SigContextType type, PRArenaPool **arena) { jclass proxyClass; jmethodID constructor; jbyteArray byteArray; SigContextProxy *proxy = NULL; jobject Context = NULL; /* arena and *arena can safely be NULL */ PR_ASSERT(env != NULL && ctxt != NULL && *ctxt != NULL); /* Create the proxy structure */ proxy = (SigContextProxy*) PR_Malloc(sizeof(SigContextProxy)); if (proxy == NULL) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } proxy->ctxt = *ctxt; proxy->type = type; proxy->arena = NULL; if (arena != NULL) { proxy->arena = *arena; } byteArray = JSS_ptrToByteArray(env, (void*)proxy); /* * Lookup the class and constructor */ proxyClass = (*env)->FindClass(env, SIG_CONTEXT_PROXY_CLASS_NAME); if (proxyClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } constructor = (*env)->GetMethodID(env, proxyClass, SIG_CONTEXT_PROXY_CONSTRUCTOR_NAME, SIG_CONTEXT_PROXY_CONSTRUCTOR_SIG); if (constructor == NULL) { ASSERT_OUTOFMEM(env); goto finish; } /* call the constructor */ Context = (*env)->NewObject(env, proxyClass, constructor, byteArray); finish: if (Context == NULL) { /* didn't work, so free resources */ if (proxy != NULL) { PR_Free(proxy); } if (type == SGN_CONTEXT) { SGN_DestroyContext((SGNContext*)*ctxt, PR_TRUE /*freeit*/); } else { PR_ASSERT(type == VFY_CONTEXT); VFY_DestroyContext((VFYContext*)*ctxt, PR_TRUE /*freeit*/); } if (arena != NULL) { PORT_FreeArena(*arena, PR_TRUE /* zero */); } } *ctxt = NULL; if (arena != NULL) { /* We either take ownership of Arena (and place in Context), or we * free it when construction fails. */ *arena = NULL; } return Context; } /*********************************************************************** * * SigContextProxy.releaseNativeResources * * Deletes the SGNContext wrapped by this SigContextProxy object. */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_SigContextProxy_releaseNativeResources (JNIEnv *env, jobject this) { SigContextProxy *proxy = NULL; /* Retrieve the proxy pointer */ if (JSS_getPtrFromProxy(env, this, (void**)&proxy) != PR_SUCCESS) { return; } if (proxy == NULL) { return; } /* Free the context and the proxy */ if(proxy->type == SGN_CONTEXT) { SGN_DestroyContext( (SGNContext*)proxy->ctxt, PR_TRUE /*freeit*/); } else { PR_ASSERT(proxy->type == VFY_CONTEXT); VFY_DestroyContext( (VFYContext*)proxy->ctxt, PR_TRUE /*freeit*/); } PORT_FreeArena(proxy->arena, PR_TRUE /* zero */); proxy->arena = NULL; PR_Free(proxy); } /*********************************************************************** * PK11Signature.engineRawSignNative */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11Signature_engineRawSignNative (JNIEnv *env, jclass clazz, jobject tokenObj, jobject keyObj, jbyteArray hashBA) { SECKEYPrivateKey *key = NULL; SECItem *sig = NULL; SECItem *hash = NULL; jbyteArray sigBA = NULL; PR_ASSERT(env!=NULL && tokenObj!=NULL && keyObj!=NULL && hashBA!=NULL); /* Get the private key */ if( JSS_PK11_getPrivKeyPtr(env, keyObj, &key) != PR_SUCCESS ) { /* exception was thrown */ goto finish; } /* get the hash */ hash = JSS_ByteArrayToSECItem(env, hashBA); /* prepare space for the sig */ sig = PR_NEW(SECItem); sig->len = PK11_SignatureLen(key); sig->data = PR_Malloc(sig->len); /* perform the signature operation */ if( PK11_Sign(key, sig, hash) != SECSuccess ) { JSS_throwMsgPrErr(env, SIGNATURE_EXCEPTION, "Signature operation failed" " on token"); goto finish; } /* convert signature to byte array */ sigBA = JSS_SECItemToByteArray(env, sig); finish: if(sig) { SECITEM_FreeItem(sig, PR_TRUE /*freeit*/); } if(hash) { SECITEM_FreeItem(hash, PR_TRUE /*freeit*/); } return sigBA; } /*********************************************************************** * PK11Signature.engineRawVerifyNative */ JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_pkcs11_PK11Signature_engineRawVerifyNative (JNIEnv *env, jclass clazz, jobject tokenObj, jobject keyObj, jbyteArray hashBA, jbyteArray sigBA) { SECItem *sig=NULL; SECItem *hash=NULL; SECKEYPublicKey *key=NULL; jboolean verified=JNI_FALSE; SECStatus status; PR_ASSERT(env!=NULL && tokenObj!=NULL && keyObj!=NULL && hashBA!=NULL && sigBA!=NULL); sig = JSS_ByteArrayToSECItem(env, sigBA); if(sig==NULL) { goto finish; } hash = JSS_ByteArrayToSECItem(env, hashBA); if(hash==NULL) { goto finish; } if( JSS_PK11_getPubKeyPtr(env, keyObj, &key) != PR_SUCCESS ) { goto finish; } /* perform the operation */ status = PK11_Verify(key, sig, hash, NULL /*wincx*/); if( status == SECSuccess ) { verified = JNI_TRUE; } else if( PR_GetError() != SEC_ERROR_BAD_SIGNATURE ) { JSS_throwMsgPrErr(env, SIGNATURE_EXCEPTION, "Verification operation" " failed on token"); goto finish; } finish: if(sig) { SECITEM_FreeItem(sig, PR_TRUE /*freeit*/); } if(hash) { SECITEM_FreeItem(hash, PR_TRUE /*freeit*/); } return verified; } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11Signature.java000066400000000000000000000326571412550063600243260ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import java.io.ByteArrayOutputStream; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.SecureRandom; import java.security.SignatureException; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.PSSParameterSpec; import org.mozilla.jss.crypto.*; import org.mozilla.jss.util.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public final class PK11Signature extends org.mozilla.jss.crypto.SignatureSpi implements java.lang.AutoCloseable { public PK11Signature(PK11Token token, SignatureAlgorithm algorithm) throws NoSuchAlgorithmException, TokenException { assert(token!=null && algorithm!=null); // Make sure this token supports this algorithm. It's OK if // it only supports the signing part; the hashing can be done // on the internal module. if( ! token.doesAlgorithm(algorithm) && ! token.doesAlgorithm(algorithm.getSigningAlg()) ) { throw new NoSuchAlgorithmException(); } this.tokenProxy = token.getProxy(); this.token = token; this.algorithm = algorithm; this.digestAlgorithm = null; /* * A RSAPSSSignature would appear like "raw", because the algorithm * matches the raw algorithm type, but we need additional parameters. */ if (!isRSAPSSAlgorithm(algorithm) && algorithm.getRawAlg() == algorithm) { raw = true; rawInput = new ByteArrayOutputStream(); } this.state = UNINITIALIZED; // If we are using RSA-PSS, save the digest algorithm to be used by // the native code. if (isRSAPSSAlgorithm(algorithm)) { try { digestAlgorithm = algorithm.getDigestAlg(); } catch (NoSuchAlgorithmException e) { digestAlgorithm = null; } } } @Override public void engineInitSign(org.mozilla.jss.crypto.PrivateKey privateKey) throws InvalidKeyException, TokenException { PK11PrivKey privKey; assert(privateKey!=null); // // Scrutinize the key. Make sure it: // -is a PKCS #11 key // -lives on this token // -is the right type for the algorithm // if( privateKey == null ) { throw new InvalidKeyException("private key is null"); } if( ! (privateKey instanceof PK11PrivKey) ) { throw new InvalidKeyException("privateKey is not a PKCS #11 "+ "private key"); } privKey = (PK11PrivKey) privateKey; try { privKey.verifyKeyIsOnToken(token); } catch(NoSuchItemOnTokenException e) { throw new InvalidKeyException(e.toString()); } try { if( KeyType.getKeyTypeFromAlgorithm(algorithm) != privKey.getKeyType()) { throw new InvalidKeyException( "Key type is inconsistent with algorithm"); } } catch( NoSuchAlgorithmException e ) { throw new InvalidKeyException("Unknown algorithm: " + algorithm, e); } // Finally, the key is OK key = privKey; // Now initialize the signature context if( ! raw ) { sigContext = null; initSigContext(); } // Don't set state until we know everything worked state = SIGN; } /************************************************************* ** This is just here for JCA compliance, we don't take randoms this way. */ @Override public void engineInitSign(org.mozilla.jss.crypto.PrivateKey privateKey, SecureRandom random) throws InvalidKeyException, TokenException { throw new RuntimeException("PK11Signature.engineInitSign() is not supported"); // engineInitSign(privateKey); } /************************************************************* ** Creates a signing context, initializes it, ** and sets the sigContext field. */ protected native void initSigContext() throws TokenException; @Override public void engineInitVerify(PublicKey publicKey) throws InvalidKeyException, TokenException { PK11PubKey pubKey; assert(publicKey!=null); // // Scrutinize the key. Make sure it: // -is a PKCS #11 key // -lives on this token // -is the right type for the algorithm // if( ! (publicKey instanceof PK11PubKey) ) { throw new InvalidKeyException("publicKey is not a PKCS #11 "+ "public key"); } pubKey = (PK11PubKey) publicKey; //try { // pubKey.verifyKeyIsOnToken(token); //} catch( NoSuchItemOnTokenException e) { // throw new InvalidKeyException(e.toString()); //} try { if( KeyType.getKeyTypeFromAlgorithm(algorithm) != pubKey.getKeyType()) { throw new InvalidKeyException( "Key type is inconsistent with algorithm"); } } catch( NoSuchAlgorithmException e ) { throw new InvalidKeyException("Unknown algorithm: " + algorithm, e); } key = pubKey; if( ! raw ) { sigContext = null; initVfyContext(); } // Don't set state until we know everything worked. state = VERIFY; } protected native void initVfyContext() throws TokenException; @Override public void engineUpdate(byte b) throws SignatureException, TokenException { engineUpdate(new byte[] {b}, 0, 1); } @Override public void engineUpdate(byte[] b, int off, int len) throws SignatureException, TokenException { assert(b != null); if( (state==SIGN || state==VERIFY) ) { if(!raw && sigContext==null) { throw new SignatureException("Signature has no context"); } else if( raw && rawInput==null) { throw new SignatureException("Raw signature has no input stream"); } } else { assert(state == UNINITIALIZED); throw new SignatureException("Signature is not initialized"); } assert(token!=null); assert(tokenProxy!=null); assert(algorithm!=null); assert(key!=null); if( raw ) { rawInput.write(b, off, len); } else { engineUpdateNative( b, off, len); } } protected native void engineUpdateNative(byte[] b, int off, int len) throws TokenException; @Override public byte[] engineSign() throws SignatureException, TokenException { if(state != SIGN) { throw new SignatureException("Signature is not initialized"); } if(!raw && sigContext==null) { throw new SignatureException("Signature has no context"); } else if(raw && rawInput==null) { throw new SignatureException("Signature has no input"); } assert(token!=null); assert(tokenProxy!=null); assert(algorithm!=null); assert(key!=null); byte[] result; if( raw ) { result = engineRawSignNative(token, (PK11PrivKey)key, rawInput.toByteArray()); rawInput.reset(); } else { result = engineSignNative(); } state = UNINITIALIZED; sigContext = null; return result; } @Override public int engineSign(byte[] outbuf, int offset, int len) throws SignatureException, TokenException { assert(outbuf!=null); byte[] sig; if( raw ) { sig = engineRawSignNative(token, (PK11PrivKey)key, rawInput.toByteArray()); rawInput.reset(); } else { sig = engineSign(); } if( (outbuf==null) || (outbuf.length <= offset) || (len < sig.length) || (offset+len > outbuf.length)) { throw new SignatureException( "outbuf is not sufficient to hold signature"); } System.arraycopy( sig, 0, outbuf, offset, sig.length); return sig.length; } /** * Performs raw signing of the given hash with the given private key. */ private static native byte[] engineRawSignNative(PK11Token token, PrivateKey key, byte[] hash) throws SignatureException, TokenException; private native byte[] engineSignNative() throws SignatureException, TokenException; @Override public boolean engineVerify(byte[] sigBytes) throws SignatureException, TokenException { assert(sigBytes!=null); if(state != VERIFY) { throw new SignatureException( "Signature is not initialized properly"); } if(!raw && sigContext==null) { throw new SignatureException("Signature has no context"); } if(raw && rawInput==null) { throw new SignatureException("Signature has no input"); } assert(token!=null); assert(tokenProxy!=null); assert(algorithm!=null); assert(key!=null); if(sigBytes==null) { return false; } boolean result; if( raw ) { result = engineRawVerifyNative(token, (PK11PubKey)key, rawInput.toByteArray(), sigBytes); rawInput.reset(); } else { result = engineVerifyNative(sigBytes); } state = UNINITIALIZED; sigContext = null; return result; } /** * Performs raw verification of the signature of a hash using the * given public key, on the given token. */ protected static native boolean engineRawVerifyNative(PK11Token token, PublicKey key, byte[] hash, byte[] signature) throws SignatureException, TokenException; native protected boolean engineVerifyNative(byte[] sigBytes) throws SignatureException, TokenException; @Override public void engineSetParameter(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException, TokenException { // For now we only care about RSA PSS parameter specs if (!isRSAPSSAlgorithm((SignatureAlgorithm) algorithm)) { String msg = "Passing algorithm parameters for this algorithm ("; msg += algorithm + ") is not supported: " + params.toString(); throw new InvalidAlgorithmParameterException(msg); } if (!(params instanceof PSSParameterSpec)) { String msg = "Unsupported algorithm parameter spec class for "; msg += "RSA/PSS: " + params.getClass().getName() + " -- "; msg += params.toString(); throw new InvalidAlgorithmParameterException(msg); } if (params == null) { String msg = "Got an unexpected null parameter spec for RSA/PSS"; throw new InvalidAlgorithmParameterException(msg); } digestAlgorithm = getRSAPSSDigestAlgFromSpec((PSSParameterSpec) params); } private Algorithm getRSAPSSDigestAlgFromSpec(PSSParameterSpec params) throws InvalidAlgorithmParameterException { String hashAlgName = params.getDigestAlgorithm(); Algorithm hashAlg = null; if (hashAlgName.equals("SHA-256")) { hashAlg = DigestAlgorithm.SHA256; } else if (hashAlgName.equals("SHA-384")) { hashAlg = DigestAlgorithm.SHA384; } else if (hashAlgName.equals("SHA-512")) { hashAlg = DigestAlgorithm.SHA512; } else { String msg = "This digest algorithm (" + hashAlgName + ") isn't "; msg += "supported for this algorithm (" + algorithm + "): "; msg += params.toString(); throw new InvalidAlgorithmParameterException(msg); } return hashAlg; } private boolean isRSAPSSAlgorithm(SignatureAlgorithm algorithm) { if (algorithm == null) { return false; } if (algorithm == SignatureAlgorithm.RSAPSSSignatureWithSHA256Digest || algorithm == SignatureAlgorithm.RSAPSSSignatureWithSHA384Digest || algorithm == SignatureAlgorithm.RSAPSSSignatureWithSHA512Digest || algorithm == SignatureAlgorithm.RSAPSSSignature) { return true; } return false; } @Override public void finalize() throws Throwable { close(); } @Override public void close() throws Exception { if (sigContext != null) { try { sigContext.close(); } finally { sigContext = null; } } } protected PK11Token token; protected TokenProxy tokenProxy; protected Algorithm algorithm; protected Algorithm digestAlgorithm; protected PK11Key key; protected int state; protected SigContextProxy sigContext; protected boolean raw=false; // raw signing only, no hashing protected ByteArrayOutputStream rawInput; // states static public final int UNINITIALIZED = 0; static public final int SIGN = 1; static public final int VERIFY = 2; } class SigContextProxy extends NativeProxy { public static Logger logger = LoggerFactory.getLogger(SigContextProxy.class); public SigContextProxy(byte[] pointer) { super(pointer); } @Override protected native void releaseNativeResources(); } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11Store.c000066400000000000000000000645251412550063600227610ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "_jni/org_mozilla_jss_pkcs11_PK11Store.h" #include #include #include #include #include #include #include #include #include #include #include "pk11util.h" #include #include typedef struct { enum { PW_NONE = 0, PW_FROMFILE = 1, PW_PLAINTEXT = 2, PW_EXTERNAL = 3 } source; char *data; } secuPWData; SECItem *preparePassword(JNIEnv *env, jobject conv, jobject pwObj); /********************************************************************** * PK11Store.putSymKeysInVector */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11Store_putSymKeysInVector (JNIEnv *env, jobject this, jobject keyVector) { PK11SlotInfo *slot; jobject object = NULL; jclass vectorClass; jmethodID addElement; PK11SymKey *firstSymKey= NULL; PK11SymKey *sk = NULL; PK11SymKey *nextSymKey = NULL; secuPWData pwdata; pwdata.source = PW_NONE; pwdata.data = (char *) NULL; PR_ASSERT(env!=NULL && this!=NULL && keyVector!=NULL); if( JSS_PK11_getStoreSlotPtr(env, this, &slot) != PR_SUCCESS) { ASSERT_OUTOFMEM(env); goto finish; } PR_ASSERT(slot!=NULL); vectorClass = (*env)->GetObjectClass(env, keyVector); if(vectorClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } addElement = (*env)->GetMethodID(env, vectorClass, VECTOR_ADD_ELEMENT_NAME, VECTOR_ADD_ELEMENT_SIG); if(addElement == NULL) { ASSERT_OUTOFMEM(env); goto finish; } PK11_Authenticate(slot, PR_TRUE /*load certs*/, NULL /*wincx*/); /* Obtain the symmetric key list. */ firstSymKey = PK11_ListFixedKeysInSlot( slot , NULL, ( void *) &pwdata ); sk = firstSymKey; while(( sk != NULL )) { if( sk ) { nextSymKey = sk; object = JSS_PK11_wrapSymKey(env, &sk); if(object == NULL) { PR_ASSERT( (*env)->ExceptionOccurred(env) ); goto finish; } /*************************************************** * Insert the key into the vector ***************************************************/ (*env)->CallVoidMethod(env, keyVector, addElement, object); } sk = PK11_GetNextSymKey( nextSymKey ); } finish: return; } /********************************************************************** * PK11Store.loadPrivateKeys */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11Store_loadPrivateKeys (JNIEnv *env, jobject this, jobject collection) { PK11SlotInfo *slot; SECKEYPrivateKeyList *list = NULL; SECKEYPrivateKeyListNode *node = NULL; SECKEYPrivateKey* key = NULL; jobject privateKey = NULL; jclass collectionClass; jmethodID collectionAdd; PR_ASSERT(env!=NULL && this!=NULL && collection!=NULL); if (JSS_PK11_getStoreSlotPtr(env, this, &slot) != PR_SUCCESS) { ASSERT_OUTOFMEM(env); goto finish; } PR_ASSERT(slot!=NULL); /* * Most, if not all, tokens have to be logged in before they allow * access to their private keys, so try to log in here. If we're already * logged in, this is a no-op. * If the login fails, go ahead and try to get the keys anyway, in case * this is an exceptionally promiscuous token. */ PK11_Authenticate(slot, PR_TRUE /*load certs*/, NULL /*wincx*/); // get the list of keys on this token list = PK11_ListPrivateKeysInSlot(slot); if (list == NULL) { JSS_throwMsg(env, TOKEN_EXCEPTION, "PK11_ListPrivateKeysInSlot " "returned an error"); goto finish; } // get Collection class collectionClass = (*env)->FindClass(env, COLLECTION_CLASS_NAME); if (collectionClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } // get Collection.add() method collectionAdd = (*env)->GetMethodID(env, collectionClass, COLLECTION_ADD_NAME, COLLECTION_ADD_SIG); if (collectionAdd == NULL) { ASSERT_OUTOFMEM(env); goto finish; } for( node = PRIVKEY_LIST_HEAD(list); !PRIVKEY_LIST_END(node, list); node = PRIVKEY_LIST_NEXT(node) ) { // wrap private key key = SECKEY_CopyPrivateKey(node->key); privateKey = JSS_PK11_wrapPrivKey(env, &key); if (privateKey == NULL) { PR_ASSERT((*env)->ExceptionOccurred(env)); goto finish; } // add private key into collection (*env)->CallBooleanMethod(env, collection, collectionAdd, privateKey); } finish: if (list != NULL) { SECKEY_DestroyPrivateKeyList(list); } return; } /********************************************************************** * PK11Store.loadPublicKeys */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11Store_loadPublicKeys (JNIEnv *env, jobject this, jobject collection) { PK11SlotInfo *slot; SECKEYPublicKeyList *list = NULL; SECKEYPublicKeyListNode *node = NULL; SECKEYPublicKey* key = NULL; jobject publicKey = NULL; jclass collectionClass; jmethodID collectionAdd; PR_ASSERT(env!=NULL && this!=NULL && collection!=NULL); if (JSS_PK11_getStoreSlotPtr(env, this, &slot) != PR_SUCCESS) { ASSERT_OUTOFMEM(env); goto finish; } PR_ASSERT(slot!=NULL); /* * Most, if not all, tokens have to be logged in before they allow * access to their public keys, so try to log in here. If we're already * logged in, this is a no-op. * If the login fails, go ahead and try to get the keys anyway, in case * this is an exceptionally promiscuous token. */ PK11_Authenticate(slot, PR_TRUE /*load certs*/, NULL /*wincx*/); // get the list of keys on this token list = PK11_ListPublicKeysInSlot(slot, NULL /*nickname*/); if (list == NULL) { JSS_throwMsg(env, TOKEN_EXCEPTION, "PK11_ListPublicKeysInSlot " "returned an error"); goto finish; } // get Collection class collectionClass = (*env)->FindClass(env, COLLECTION_CLASS_NAME); if (collectionClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } // get Collection.add() method collectionAdd = (*env)->GetMethodID(env, collectionClass, COLLECTION_ADD_NAME, COLLECTION_ADD_SIG); if (collectionAdd == NULL) { ASSERT_OUTOFMEM(env); goto finish; } for( node = PUBKEY_LIST_HEAD(list); !PUBKEY_LIST_END(node, list); node = PUBKEY_LIST_NEXT(node) ) { // wrap public key key = SECKEY_CopyPublicKey(node->key); publicKey = JSS_PK11_wrapPubKey(env, &key); if (publicKey == NULL) { PR_ASSERT((*env)->ExceptionOccurred(env)); goto finish; } // add public key into collection (*env)->CallBooleanMethod(env, collection, collectionAdd, publicKey); } finish: if (list != NULL) { SECKEY_DestroyPublicKeyList(list); } return; } /********************************************************************** * PK11Store.putCertsInVector */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11Store_putCertsInVector (JNIEnv *env, jobject this, jobject certVector) { PK11SlotInfo *slot; PK11SlotInfo *slotCopy; jclass vectorClass; jmethodID addElement; CERTCertList *certList = NULL; CERTCertificate *certCopy; CERTCertListNode *node = NULL; jobject object; PR_ASSERT(env!=NULL && this!=NULL && certVector!=NULL); if( JSS_PK11_getStoreSlotPtr(env, this, &slot) != PR_SUCCESS) { ASSERT_OUTOFMEM(env); goto finish; } PR_ASSERT(slot!=NULL); /* * log in if the slot does not have publicly readable certs */ if( !PK11_IsFriendly(slot) ) { PK11_Authenticate(slot, PR_TRUE /*load certs*/, NULL /*wincx*/); } certList = PK11_ListCertsInSlot(slot); if( certList == NULL ) { JSS_throwMsg(env, TOKEN_EXCEPTION, "PK11_ListCertsInSlot " "returned an error"); goto finish; } /************************************************** * Get JNI ids **************************************************/ vectorClass = (*env)->GetObjectClass(env, certVector); if(vectorClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } addElement = (*env)->GetMethodID(env, vectorClass, VECTOR_ADD_ELEMENT_NAME, VECTOR_ADD_ELEMENT_SIG); if(addElement == NULL) { ASSERT_OUTOFMEM(env); goto finish; } for( node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList); node = CERT_LIST_NEXT(node) ) { /*************************************************** * Wrap the object ***************************************************/ certCopy = CERT_DupCertificate(node->cert); slotCopy = PK11_ReferenceSlot(slot); object = JSS_PK11_wrapCertAndSlotAndNickname(env, &certCopy, &slotCopy, node->appData); if(object == NULL) { PR_ASSERT( (*env)->ExceptionOccurred(env) ); goto finish; } /*************************************************** * Insert the cert into the vector ***************************************************/ (*env)->CallVoidMethod(env, certVector, addElement, object); } finish: if( certList != NULL ) { CERT_DestroyCertList(certList); } return; } /************************************************************************ * * J S S _ g e t S t o r e S l o t P t r * * Retrieve the PK11SlotInfo pointer of the given PK11Store. * * INPUTS * store * A reference to a Java PK11Store * slot * address of a PK11SlotInfo* that will be loaded with * the PK11SlotInfo pointer of the given token. * RETURNS * PR_SUCCESS if the operation was successful, PR_FAILURE if an * exception was thrown. */ PRStatus JSS_PK11_getStoreSlotPtr(JNIEnv *env, jobject store, PK11SlotInfo **slot) { PR_ASSERT(env!=NULL && store!=NULL && slot!=NULL); return JSS_getPtrFromProxyOwner(env, store, PK11STORE_PROXY_FIELD, PK11STORE_PROXY_SIG, (void**)slot); } /********************************************************************** * PK11Store.deletePrivateKey */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11Store_deletePrivateKey (JNIEnv *env, jobject this, jobject privateKeyObj) { PK11SlotInfo *slot; SECKEYPrivateKey *privateKey; PR_ASSERT(env!=NULL && this!=NULL); if (privateKeyObj == NULL) { JSS_throw(env, NO_SUCH_ITEM_ON_TOKEN_EXCEPTION); goto finish; } if (JSS_PK11_getStoreSlotPtr(env, this, &slot) != PR_SUCCESS) { PR_ASSERT((*env)->ExceptionOccurred(env) != NULL); goto finish; } if (JSS_PK11_getPrivKeyPtr(env, privateKeyObj, &privateKey) != PR_SUCCESS) { PR_ASSERT((*env)->ExceptionOccurred(env) != NULL); goto finish; } /* A private key may be temporary, but you can't use this function * to delete it. Instead, just let it be garbage collected */ if (privateKey->pkcs11IsTemp) { PR_ASSERT(PR_FALSE); JSS_throwMsg(env, TOKEN_EXCEPTION, "Private Key is not a permanent PKCS #11 object"); goto finish; } if (slot != privateKey->pkcs11Slot) { JSS_throw(env, NO_SUCH_ITEM_ON_TOKEN_EXCEPTION); goto finish; } if (PK11_DestroyTokenObject(privateKey->pkcs11Slot, privateKey->pkcs11ID) != SECSuccess) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to remove private key"); goto finish; } finish: return; } /********************************************************************** * PK11Store.deletePublicKey */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11Store_deletePublicKey (JNIEnv *env, jobject this, jobject publicKeyObj) { PK11SlotInfo *slot; SECKEYPublicKey *publicKey; PR_ASSERT(env != NULL && this != NULL); if (publicKeyObj == NULL) { JSS_throw(env, NO_SUCH_ITEM_ON_TOKEN_EXCEPTION); goto finish; } if (JSS_PK11_getStoreSlotPtr(env, this, &slot) != PR_SUCCESS) { PR_ASSERT((*env)->ExceptionOccurred(env) != NULL); goto finish; } if (JSS_PK11_getPubKeyPtr(env, publicKeyObj, &publicKey) != PR_SUCCESS) { PR_ASSERT((*env)->ExceptionOccurred(env) != NULL); goto finish; } if (slot != publicKey->pkcs11Slot) { JSS_throw(env, NO_SUCH_ITEM_ON_TOKEN_EXCEPTION); goto finish; } if (PK11_DestroyTokenObject(publicKey->pkcs11Slot, publicKey->pkcs11ID) != SECSuccess) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Unable to remove public key"); goto finish; } finish: return; } /********************************************************************** * PK11Store.deleteCert * * This function deletes the specified certificate and its associated * private key. */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11Store_deleteCert (JNIEnv *env, jobject this, jobject certObject) { CERTCertificate *cert; SECStatus VARIABLE_MAY_NOT_BE_USED status; PR_ASSERT(env!=NULL && this!=NULL); if(certObject == NULL) { JSS_throw(env, NO_SUCH_ITEM_ON_TOKEN_EXCEPTION); goto finish; } if( JSS_PK11_getCertPtr(env, certObject, &cert) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } status = PK11_DeleteTokenCertAndKey(cert, NULL); status = SEC_DeletePermCertificate(cert); finish: return; } /********************************************************************** * PK11Store.deleteCertOnly * * This function deletes the specified certificate only. */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11Store_deleteCertOnly (JNIEnv *env, jobject this, jobject certObject) { CERTCertificate *cert; SECStatus VARIABLE_MAY_NOT_BE_USED status; PR_ASSERT(env!=NULL && this!=NULL); if(certObject == NULL) { JSS_throw(env, NO_SUCH_ITEM_ON_TOKEN_EXCEPTION); goto finish; } if( JSS_PK11_getCertPtr(env, certObject, &cert) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } status = SEC_DeletePermCertificate(cert); finish: return; } #define DER_DEFAULT_CHUNKSIZE (2048) int PK11_NumberObjectsFor(PK11SlotInfo*, CK_ATTRIBUTE*, int); /*********************************************************************** * PK11Store.importdPrivateKey */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11Store_importPrivateKey ( JNIEnv *env, jobject this, jbyteArray keyArray, jobject keyTypeObj, jboolean temporary ) { SECItem derPK; PK11SlotInfo *slot; jthrowable excep; SECStatus status; SECItem nickname; jobject privkObj = NULL; /* * initialize so we can goto finish */ derPK.data = NULL; derPK.len = 0; PR_ASSERT(env!=NULL && this!=NULL); if(keyArray == NULL) { JSS_throw(env, NULL_POINTER_EXCEPTION); goto finish; } /* * copy the java byte array into a local copy */ if (!JSS_RefByteArray(env, keyArray, (jbyte **) &derPK.data, (jsize *) &derPK.len)) { if (derPK.len == 0) { JSS_throwMsg(env, INVALID_KEY_FORMAT_EXCEPTION, "Key array is empty"); } else { ASSERT_OUTOFMEM(env); } goto finish; } /* * Get the PKCS #11 slot */ if( JSS_PK11_getStoreSlotPtr(env, this, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } nickname.len = 0; nickname.data = NULL; SECKEYPrivateKey *privk = NULL; status = PK11_ImportDERPrivateKeyInfoAndReturnKey( slot, &derPK, &nickname, NULL /*public value*/, !temporary /*isPerm*/, PR_TRUE /*isPrivate*/, 0 /*keyUsage*/, &privk, NULL /*wincx*/); if(status != SECSuccess) { JSS_throwMsg(env, TOKEN_EXCEPTION, "Failed to import private key info"); goto finish; } privkObj = JSS_PK11_wrapPrivKey(env, &privk); if (privkObj == NULL) { goto finish; } finish: /* Save any exceptions */ if( (excep=(*env)->ExceptionOccurred(env)) ) { (*env)->ExceptionClear(env); } JSS_DerefByteArray(env, keyArray, derPK.data, JNI_ABORT); /* now re-throw the exception */ if( excep ) { (*env)->Throw(env, excep); } return privkObj; } extern const SEC_ASN1Template SECKEY_EncryptedPrivateKeyInfoTemplate[]; JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11Store_getEncryptedPrivateKeyInfo( JNIEnv *env, jobject this, jobject conv, jobject pwObj, jobject algObj, jint iterations, jobject key) { // initialisations so we can goto finish SECItem *pwItem = NULL; SECKEYEncryptedPrivateKeyInfo *epki = NULL; SECItem epkiItem; epkiItem.data = NULL; epkiItem.len = 0; jbyteArray encodedEpki = NULL; PR_ASSERT(env != NULL && this != NULL); if (pwObj == NULL || algObj == NULL || key == NULL) { JSS_throw(env, NULL_POINTER_EXCEPTION); goto finish; } if (iterations <= 0) { iterations = 2000; // set default iterations } // get slot PK11SlotInfo *slot = NULL; if( JSS_PK11_getStoreSlotPtr(env, this, &slot) != PR_SUCCESS) { ASSERT_OUTOFMEM(env); goto finish; } PR_ASSERT(slot!=NULL); // get algorithm SECOidTag algTag = JSS_getOidTagFromAlg(env, algObj); if (algTag == SEC_OID_UNKNOWN) { JSS_throwMsg(env, NO_SUCH_ALG_EXCEPTION, "Unrecognized algorithm"); goto finish; } pwItem = preparePassword(env, conv, pwObj); if (pwItem == NULL) { ASSERT_OUTOFMEM(env); goto finish; } // get key SECKEYPrivateKey *privk; if (JSS_PK11_getPrivKeyPtr(env, key, &privk) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } // export the epki epki = PK11_ExportEncryptedPrivKeyInfo( slot, algTag, pwItem, privk, iterations, NULL /*wincx*/); if (epki == NULL) { //try our own version for the new AES KWP algs. epki = JSS_ExportEncryptedPrivKeyInfoV2( slot, algTag, /* PBE algorithm to encrypt the key with */ SEC_OID_UNKNOWN, /* Encryption algorithm to Encrypt the key with */ SEC_OID_UNKNOWN, /* Hash algorithm for PRF */ pwItem, /* password for PBE encryption */ privk, /* encrypt this private key */ iterations, /* interations for PBE alg */ NULL); if(epki == NULL) { JSS_throwMsgPrErr( env, TOKEN_EXCEPTION, "Failed to export EncryptedPrivateKeyInfo"); goto finish; } } // DER-encode the epki if (SEC_ASN1EncodeItem(NULL, &epkiItem, epki, SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate)) == NULL) { JSS_throwMsg( env, TOKEN_EXCEPTION, "Failed to ASN1-encode EncryptedPrivateKeyInfo"); goto finish; } // convert to Java byte array encodedEpki = JSS_SECItemToByteArray(env, &epkiItem); finish: if (epki != NULL) { SECKEY_DestroyEncryptedPrivateKeyInfo(epki, PR_TRUE /*freeit*/); } if (epkiItem.data != NULL) { SECITEM_FreeItem(&epkiItem, PR_FALSE /*freeit*/); } if (pwItem != NULL) { SECITEM_FreeItem(pwItem, PR_TRUE /*freeit*/); } return encodedEpki; } JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11Store_importEncryptedPrivateKeyInfo( JNIEnv *env, jobject this, jobject conv, jobject pwObj, jstring nickname, jobject pubKeyObj, jbyteArray epkiBytes) { // initialisations so we can goto finish SECItem *epkiItem = NULL; SECKEYEncryptedPrivateKeyInfo *epki = NULL; SECItem *pwItem = NULL; SECItem *spkiItem = NULL; CERTSubjectPublicKeyInfo *spki = NULL; SECKEYPublicKey *pubKey = NULL; const char *nicknameChars = NULL; PR_ASSERT(env != NULL && this != NULL); if (pwObj == NULL || nickname == NULL || pubKeyObj == NULL) { JSS_throw(env, NULL_POINTER_EXCEPTION); goto finish; } // get slot PK11SlotInfo *slot = NULL; if (JSS_PK11_getStoreSlotPtr(env, this, &slot) != PR_SUCCESS) { ASSERT_OUTOFMEM(env); goto finish; } PR_ASSERT(slot != NULL); // decode EncryptedPrivateKeyInfo epkiItem = JSS_ByteArrayToSECItem(env, epkiBytes); epki = PR_Calloc(1, sizeof(SECKEYEncryptedPrivateKeyInfo)); if (SEC_ASN1DecodeItem( NULL, epki, SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate), epkiItem ) != SECSuccess) { JSS_throwMsg(env, INVALID_DER_EXCEPTION, "Failed to decode EncryptedPrivateKeyInfo"); goto finish; } pwItem = preparePassword(env, conv, pwObj); if (pwItem == NULL) { ASSERT_OUTOFMEM(env); goto finish; } // get public key value jclass pubKeyClass = (*env)->GetObjectClass(env, pubKeyObj); if (pubKeyClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } jmethodID getEncoded = (*env)->GetMethodID( env, pubKeyClass, "getEncoded", "()[B"); if (getEncoded == NULL) { ASSERT_OUTOFMEM(env); goto finish; } jbyteArray spkiBytes = (*env)->CallObjectMethod( env, pubKeyObj, getEncoded); spkiItem = JSS_ByteArrayToSECItem(env, spkiBytes); spki = PR_Calloc(1, sizeof(CERTSubjectPublicKeyInfo)); if (SEC_ASN1DecodeItem( NULL, spki, SEC_ASN1_GET(CERT_SubjectPublicKeyInfoTemplate), spkiItem ) != SECSuccess) { JSS_throwMsg(env, INVALID_DER_EXCEPTION, "Failed to decode SubjectPublicKeyInfo"); goto finish; } pubKey = SECKEY_ExtractPublicKey(spki); if (pubKey == NULL) { JSS_throwMsgPrErr(env, INVALID_DER_EXCEPTION, "Failed to extract public key from SubjectPublicKeyInfo"); goto finish; } SECItem *pubValue; switch (pubKey->keyType) { case dsaKey: pubValue = &pubKey->u.dsa.publicValue; break; case dhKey: pubValue = &pubKey->u.dh.publicValue; break; case rsaKey: pubValue = &pubKey->u.rsa.modulus; break; case ecKey: pubValue = &pubKey->u.ec.publicValue; break; default: pubValue = NULL; } // prepare nickname nicknameChars = JSS_RefJString(env, nickname); if (nicknameChars == NULL) { ASSERT_OUTOFMEM(env); goto finish; } SECItem nickItem; nickItem.data = (unsigned char *) nicknameChars; nickItem.len = (*env)->GetStringUTFLength(env, nickname); // if keyUsage = 0, defaults to signing and encryption/key agreement. // see pk11akey.c in NSS int keyUsage = 0; // perform import SECStatus result = PK11_ImportEncryptedPrivateKeyInfo( slot, epki, pwItem, &nickItem, pubValue, PR_TRUE /* isperm */, PR_TRUE /* isprivate */, pubKey->keyType, keyUsage, NULL /* wincx */); if (result != SECSuccess) { JSS_throwMsgPrErr( env, TOKEN_EXCEPTION, "Failed to import EncryptedPrivateKeyInfo to token"); goto finish; } // Attempt to store the public key in the token. // Failure is non-fatal (some tokens cannot store the public key). PK11_ImportPublicKey(slot, pubKey, PR_TRUE /* isToken (permanent) */); finish: if (epkiItem != NULL) { SECITEM_FreeItem(epkiItem, PR_TRUE /*freeit*/); } if (epki != NULL) { SECKEY_DestroyEncryptedPrivateKeyInfo(epki, PR_TRUE /*freeit*/); } if (spkiItem != NULL) { SECITEM_FreeItem(spkiItem, PR_TRUE /*freeit*/); } if (spki != NULL) { SECKEY_DestroySubjectPublicKeyInfo(spki); } if (pwItem != NULL) { SECITEM_FreeItem(pwItem, PR_TRUE /*freeit*/); } if (pubKey != NULL) { SECKEY_DestroyPublicKey(pubKey); } JSS_DerefJString(env, nickname, nicknameChars); } /* Process the given password through the given PasswordConverter, * returning a new SECItem* on success. * * After use, the caller should free the SECItem: * * SECITEM_FreeItem(pwItem, PR_TRUE). */ SECItem *preparePassword(JNIEnv *env, jobject conv, jobject pwObj) { jclass passwordClass = (*env)->GetObjectClass(env, pwObj); if (passwordClass == NULL) { ASSERT_OUTOFMEM(env); return NULL; } jbyteArray pwBytes; if (conv == NULL) { jmethodID getByteCopy = (*env)->GetMethodID( env, passwordClass, PW_GET_BYTE_COPY_NAME, PW_GET_BYTE_COPY_SIG); if (getByteCopy == NULL) { ASSERT_OUTOFMEM(env); return NULL; } pwBytes = (*env)->CallObjectMethod(env, pwObj, getByteCopy); } else { jmethodID getChars = (*env)->GetMethodID( env, passwordClass, "getChars", "()[C"); if (getChars == NULL) { ASSERT_OUTOFMEM(env); return NULL; } jcharArray pwChars = (*env)->CallObjectMethod(env, pwObj, getChars); jclass convClass = (*env)->GetObjectClass(env, conv); if (conv == NULL) { ASSERT_OUTOFMEM(env); return NULL; } jmethodID convert = (*env)->GetMethodID( env, convClass, "convert", "([C)[B"); if (convert == NULL) { ASSERT_OUTOFMEM(env); return NULL; } pwBytes = (*env)->CallObjectMethod(env, conv, convert, pwChars); } return JSS_ByteArrayToSECItem(env, pwBytes); } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11Store.java000066400000000000000000000170331412550063600234500ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import java.math.BigInteger; import java.security.PublicKey; import java.security.interfaces.RSAKey; import java.security.interfaces.RSAPublicKey; import java.util.ArrayList; import java.util.Collection; import java.util.Vector; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.crypto.Algorithm; import org.mozilla.jss.crypto.CryptoStore; import org.mozilla.jss.crypto.KeyAlreadyImportedException; import org.mozilla.jss.crypto.KeyGenerator; import org.mozilla.jss.crypto.NoSuchItemOnTokenException; import org.mozilla.jss.crypto.ObjectNotFoundException; import org.mozilla.jss.crypto.PBEAlgorithm; import org.mozilla.jss.crypto.PrivateKey; import org.mozilla.jss.crypto.SymmetricKey; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.crypto.X509Certificate; import org.mozilla.jss.util.Password; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public final class PK11Store implements CryptoStore { public static Logger logger = LoggerFactory.getLogger(PK11Store.class); //////////////////////////////////////////////////////////// // Private Keys //////////////////////////////////////////////////////////// /** * Imports a raw private key into this token. * * @param key The private key. * @exception TokenException If the key cannot be imported to this token. * @exception KeyAlreadyImportedException If the key already on this token. */ @Override public PrivateKey importPrivateKey(byte[] key, PrivateKey.Type type) throws TokenException,KeyAlreadyImportedException { return importPrivateKey(key, type, false); } @Override public native PrivateKey importPrivateKey( byte[] key, PrivateKey.Type type, boolean temporary) throws TokenException,KeyAlreadyImportedException; @Override public synchronized PrivateKey[] getPrivateKeys() throws TokenException { ArrayList list = new ArrayList<>(); loadPrivateKeys(list); PrivateKey[] array = new PrivateKey[list.size()]; list.toArray(array); return array; } protected native void loadPrivateKeys(Collection privateKeys) throws TokenException; @Override public synchronized PublicKey[] getPublicKeys() throws TokenException { ArrayList list = new ArrayList<>(); loadPublicKeys(list); PublicKey[] array = new PublicKey[list.size()]; list.toArray(array); return array; } protected native void loadPublicKeys(Collection privateKeys) throws TokenException; @Override public PublicKey findPublicKey(PrivateKey privateKey) throws TokenException, ObjectNotFoundException { // NSS does not provide a function to find the public key of a private key, // so it has to be done manually. if (privateKey instanceof RSAKey) { logger.debug("PKCS11Store: searching for RSA public key"); RSAKey rsaPrivateKey = (RSAKey) privateKey; BigInteger modulus = rsaPrivateKey.getModulus(); // Find the RSA public key by comparing the modulus. for (PublicKey publicKey : getPublicKeys()) { if (!(publicKey instanceof RSAPublicKey)) { // not an RSA public key continue; } RSAPublicKey rsaPublicKey = (RSAPublicKey) publicKey; if (!modulus.equals(rsaPublicKey.getModulus())) { // modulus doesn't match continue; } logger.debug("PKCS11Store: found RSA public key"); return publicKey; } } else { // TODO: add support for non-RSA keys } throw new ObjectNotFoundException("Unable to find public key"); } @Override public synchronized SymmetricKey[] getSymmetricKeys() throws TokenException { Vector keys = new Vector<>(); putSymKeysInVector(keys); SymmetricKey[] array = new SymmetricKey[keys.size()]; keys.copyInto( array); return array; } protected native void putSymKeysInVector(Vector symKeys) throws TokenException; @Override public native void deletePrivateKey(PrivateKey privateKey) throws NoSuchItemOnTokenException, TokenException; @Override public native void deletePublicKey(PublicKey publicKey) throws NoSuchItemOnTokenException, TokenException; @Override public byte[] getEncryptedPrivateKeyInfo( X509Certificate cert, PBEAlgorithm pbeAlg, Password pw, int iteration) throws NotInitializedException, ObjectNotFoundException, TokenException { return getEncryptedPrivateKeyInfo( null, pw, pbeAlg, iteration, CryptoManager.getInstance().findPrivKeyByCert(cert) ); } @Override public native byte[] getEncryptedPrivateKeyInfo( KeyGenerator.CharToByteConverter conv, Password pw, Algorithm alg, int n, PrivateKey k); @Override public native void importEncryptedPrivateKeyInfo( KeyGenerator.CharToByteConverter conv, Password pw, String nickname, PublicKey pubKey, byte[] epkiBytes); //////////////////////////////////////////////////////////// // Certs //////////////////////////////////////////////////////////// @Override public X509Certificate[] getCertificates() throws TokenException { Vector certs = new Vector<>(); putCertsInVector(certs); X509Certificate[] array = new X509Certificate[certs.size()]; certs.copyInto( array ); return array; } protected native void putCertsInVector(Vector certs) throws TokenException; /** * Deletes the specified certificate and its associated private * key from the store. * * @param cert certificate to be deleted * @exception NoSuchItemOnTokenException If the certificate not found * @exception TokenException General token error */ // Currently have to use PK11_DeleteTokenObject + PK11_FindObjectForCert // or maybe SEC_DeletePermCertificate. @Override public native void deleteCert(X509Certificate cert) throws NoSuchItemOnTokenException, TokenException; /** * Deletes the specified certificate from the store. * * @param cert certificate to be deleted * @exception NoSuchItemOnTokenException If the certificate not found * @exception TokenException General token error */ @Override public native void deleteCertOnly(X509Certificate cert) throws NoSuchItemOnTokenException, TokenException; //////////////////////////////////////////////////////////// // Construction //////////////////////////////////////////////////////////// protected boolean updated; public PK11Store(TokenProxy proxy) { assert(proxy!=null); this.storeProxy = proxy; } protected PK11Store() { } //////////////////////////////////////////////////////////// // Private data //////////////////////////////////////////////////////////// protected TokenProxy storeProxy; } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11SymKey.c000066400000000000000000000233201412550063600230720ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "_jni/org_mozilla_jss_pkcs11_SymKeyProxy.h" #include #include #include #include #include #include #include #include "pk11util.h" /* For PKCS#11 v3.0 compatibility */ #ifndef CKM_NSS_PBE_SHA1_DES_CBC #define CKM_NSS_PBE_SHA1_DES_CBC (CKM_NETSCAPE_PBE_SHA1_DES_CBC) #endif /*********************************************************************** * * J S S _ P K 1 1 _ w r a p S y m K e y * Puts a Symmetric Key into a Java object. * (Does NOT perform a cryptographic "wrap" operation.) * symKey: will be stored in a Java wrapper. * Returns: a new PK11SymKey, or NULL if an exception occurred. */ jobject JSS_PK11_wrapSymKey(JNIEnv *env, PK11SymKey **symKey) { jclass keyClass; jmethodID constructor; jbyteArray ptrArray; jobject Key=NULL; char *nickname = NULL; jstring jnickname = NULL; PR_ASSERT(env!=NULL && symKey!=NULL && *symKey!=NULL); /* find the class */ keyClass = (*env)->FindClass(env, PK11SYMKEY_CLASS_NAME); if( keyClass == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } nickname = PK11_GetSymKeyNickname( *symKey ); if (nickname) { jnickname = (*env)->NewStringUTF(env, nickname); } /* find the constructor */ constructor = (*env)->GetMethodID(env, keyClass, PLAIN_CONSTRUCTOR, PK11SYMKEY_CONSTRUCTOR_1_SIG); if(constructor == NULL) { ASSERT_OUTOFMEM(env); goto finish; } /* convert the pointer to a byte array */ ptrArray = JSS_ptrToByteArray(env, (void*)*symKey); if( ptrArray == NULL ) { goto finish; } /* call the constructor */ Key = (*env)->NewObject(env, keyClass, constructor, ptrArray, jnickname); finish: if(Key == NULL) { PK11_FreeSymKey(*symKey); } if(nickname != NULL) { PORT_Free(nickname); nickname = NULL; } *symKey = NULL; return Key; } /*********************************************************************** * * PK11SymKey.getOwningToken */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11SymKey_getOwningToken (JNIEnv *env, jobject this) { PK11SymKey *key = NULL; PK11SlotInfo *slot = NULL; jobject token = NULL; PR_ASSERT(env!=NULL && this!=NULL); /* Get the C key structure */ if( JSS_PK11_getSymKeyPtr(env, this, &key) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } /* Get the slot this key lives on */ slot = PK11_GetSlotFromKey(key); PR_ASSERT(slot != NULL); /* Turn the slot into a Java PK11Token */ token = JSS_PK11_wrapPK11Token(env, &slot); if(token == NULL) { PR_ASSERT( (*env)->ExceptionOccurred(env) ); goto finish; } finish: if(slot != NULL) { PK11_FreeSlot(slot); } return token; } /*********************************************************************** * * PK11SymKey.getStrength */ JNIEXPORT jint JNICALL Java_org_mozilla_jss_pkcs11_PK11SymKey_getStrength (JNIEnv *env, jobject this) { PK11SymKey *key=NULL; int strength = 0; /* get the key pointer */ if( JSS_PK11_getSymKeyPtr(env, this, &key) != PR_SUCCESS) { goto finish; } strength = PK11_GetKeyStrength(key, NULL /*algid*/); finish: return strength; } /*********************************************************************** * * PK11SymKey.getLength */ JNIEXPORT jint JNICALL Java_org_mozilla_jss_pkcs11_PK11SymKey_getLength (JNIEnv *env, jobject this) { PK11SymKey *key=NULL; unsigned int strength = 0; /* get the key pointer */ if( JSS_PK11_getSymKeyPtr(env, this, &key) != PR_SUCCESS) { goto finish; } strength = PK11_GetKeyLength(key); finish: return (jint) strength; } /*********************************************************************** * * PK11SymKey.setNickNameNative */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11SymKey_setNickNameNative (JNIEnv *env, jobject this,jstring nickname) { PK11SymKey *key=NULL; const char *keyname = NULL; SECStatus status; /* If no nickname provided, we are done */ if( nickname == NULL ) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Nickname is NULL, will not be set"); goto finish; } /* get the key pointer */ if( JSS_PK11_getSymKeyPtr(env, this, &key) != PR_SUCCESS) { goto finish; } /* convert the Java String into a native "C" string */ keyname = JSS_RefJString(env, nickname); /* name the key */ status = PK11_SetSymKeyNickname( key, keyname ); if( status != SECSuccess ) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to name symmetric key"); } finish: /* free the native "C" string */ JSS_DerefJString(env, nickname, keyname); } /*********************************************************************** * * PK11SymKey.getKeyData */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_pkcs11_PK11SymKey_getKeyData (JNIEnv *env, jobject this) { PK11SymKey *key=NULL; SECItem *keyData; /* a reference to the key data */ jbyteArray dataArray=NULL; /* get the key pointer */ if( JSS_PK11_getSymKeyPtr(env, this, &key) != PR_SUCCESS) { goto finish; } /* Extract the key data */ if( PK11_ExtractKeyValue(key) != SECSuccess ) { /* key is not extractable */ JSS_throwMsg(env, NOT_EXTRACTABLE_EXCEPTION, "Unable to extract " "symmetric key data"); goto finish; } keyData = PK11_GetKeyData(key); /* PK11_ExtractKeyValue should have failed if keyData is NULL */ PR_ASSERT(keyData != NULL); /* copy the key data into a Java byte array */ dataArray = JSS_SECItemToByteArray(env, keyData); finish: /* keyData is just a reference, nothing to free */ if( dataArray == NULL) { PR_ASSERT( (*env)->ExceptionOccurred(env) ); } return dataArray; } /*********************************************************************** * * PK11SymKey.getKeyType */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11SymKey_getKeyType (JNIEnv *env, jobject this) { PK11SymKey *key=NULL; CK_MECHANISM_TYPE keyMech; char *typeFieldName=NULL; jclass typeClass=NULL; jfieldID typeField=NULL; jobject typeObject=NULL; if( JSS_PK11_getSymKeyPtr(env, this, &key) != PR_SUCCESS ) { ASSERT_OUTOFMEM(env); goto finish; } /* Look up the key type from the key */ keyMech = PK11_GetMechanism(key); switch(keyMech) { /* PBE mechanisms have to be handled by hand */ case CKM_PBE_MD2_DES_CBC: case CKM_PBE_MD5_DES_CBC: case CKM_NSS_PBE_SHA1_DES_CBC: typeFieldName = DES_KEYTYPE_FIELD; break; case CKM_PBE_SHA1_RC4_128: case CKM_PBE_SHA1_RC4_40: typeFieldName = RC4_KEYTYPE_FIELD; break; case CKM_PBE_SHA1_RC2_128_CBC: case CKM_PBE_SHA1_RC2_40_CBC: typeFieldName = RC2_KEYTYPE_FIELD; break; case CKM_PBE_SHA1_DES3_EDE_CBC: typeFieldName = DES3_KEYTYPE_FIELD; break; case CKM_PBA_SHA1_WITH_SHA1_HMAC: typeFieldName = SHA1_HMAC_KEYTYPE_FIELD; break; default: keyMech = PK11_GetKeyType( keyMech, 0 ); switch(keyMech) { case CKK_DES: typeFieldName = DES_KEYTYPE_FIELD; break; case CKK_DES3: typeFieldName = DES3_KEYTYPE_FIELD; break; case CKK_RC4: typeFieldName = RC4_KEYTYPE_FIELD; break; case CKK_RC2: typeFieldName = RC2_KEYTYPE_FIELD; break; case CKK_AES: typeFieldName = AES_KEYTYPE_FIELD; break; case CKK_DES2: typeFieldName = DES3_KEYTYPE_FIELD; break; case CKK_GENERIC_SECRET: typeFieldName = GENERIC_SECRET_KEYTYPE_FIELD; break; default: PR_ASSERT(PR_FALSE); typeFieldName = DES_KEYTYPE_FIELD; break; } break; } /* convert to a Java key type */ typeClass = (*env)->FindClass(env, KEYTYPE_CLASS_NAME); if(typeClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } typeField = (*env)->GetStaticFieldID(env, typeClass, typeFieldName, KEYTYPE_FIELD_SIG); if(typeField == NULL) { ASSERT_OUTOFMEM(env); goto finish; } typeObject = (*env)->GetStaticObjectField(env, typeClass, typeField); if(typeObject == NULL) { ASSERT_OUTOFMEM(env); goto finish; } finish: return typeObject; } /*********************************************************************** * * J S S _ P K 1 1 _ g e t S y m K e y P t r * */ PRStatus JSS_PK11_getSymKeyPtr(JNIEnv *env, jobject symKeyObject, PK11SymKey **ptr) { PR_ASSERT(env!=NULL && symKeyObject!=NULL); /* Get the pointer from the key proxy */ return JSS_getPtrFromProxyOwner(env, symKeyObject, SYM_KEY_PROXY_FIELD, SYM_KEY_PROXY_SIG, (void**)ptr); } /*********************************************************************** * * SymKeyProxy.releaseNativeResources */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_SymKeyProxy_releaseNativeResources (JNIEnv *env, jobject this) { PK11SymKey *key=NULL; PR_ASSERT(env!=NULL && this!=NULL); if (JSS_getPtrFromProxy(env, this, (void**)&key) == PR_SUCCESS && key != NULL) { PK11_FreeSymKey(key); } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11SymKey.java000066400000000000000000000060431412550063600235740ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.SymmetricKey; // We've updated jss.crypto.SymmetricKey to extend javax.crypto.SecretKey, so // PK11SymKey implements that interface as well. public final class PK11SymKey implements SymmetricKey { protected PK11SymKey(byte[] pointer) { assert(pointer!=null); keyProxy = new SymKeyProxy(pointer); nickName = null; } protected PK11SymKey(byte[] pointer,String nickName) { assert(pointer!=null); keyProxy = new SymKeyProxy(pointer); this.nickName = nickName; } private SymKeyProxy keyProxy; private String nickName; @Override public SymmetricKey.Type getType() { KeyType kt = getKeyType(); SymmetricKey.Type result = SymmetricKey.Type.fromKeyType(kt); if (result == null) { throw new RuntimeException("Unrecognized key type: " + kt); } return result; } @Override public native CryptoToken getOwningToken(); /** * Returns key strength, measured as the number of bits of secret material. * NOTE: Due to a bug in the security library (333440), this * may return a wrong answer for PBE keys that have embedded parity * (like DES). A DES key is 56 bits of information plus * 8 bits of parity, so it takes up 64 bits. For a normal DES key, * this method will correctly return 56, but for a PBE-generated DES key, * the security library bug causes it to return 64. */ @Override public native int getStrength(); /** * Returns the length of the key in bytes, as returned by * PK11_GetKeyLength(). */ @Override public native int getLength(); @Override public native byte[] getKeyData() throws SymmetricKey.NotExtractableException; public native KeyType getKeyType(); @Override public String getAlgorithm() { return getKeyType().toString(); } @Override public byte[] getEncoded() { try { return getKeyData(); } catch(SymmetricKey.NotExtractableException nee) { return null; } } @Override public String getFormat() { return "RAW"; } @Override public String getNickName() { return nickName; } @Override public void setNickName(String nickName) { this.nickName = nickName; if( nickName != null) { setNickNameNative(nickName); } } public native void setNickNameNative(String nickName); } class SymKeyProxy extends KeyProxy { public SymKeyProxy(byte[] pointer) { super(pointer); } @Override protected native void releaseNativeResources(); @Override protected void finalize() throws Throwable { super.finalize(); } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11SymmetricKeyDeriver.c000066400000000000000000000235471412550063600256320ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "_jni/org_mozilla_jss_pkcs11_PK11SymmetricKeyDeriver.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "java_ids.h" #include "pk11util.h" #include /*********************************************************************** * Expose the NSS functionality at low level, one should know what to do * at the Java level. */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_pkcs11_PK11SymmetricKeyDeriver_nativeDeriveSymKey (JNIEnv * env, jobject this,jobject tokenObj, jobject baseKeyObj, jobject secondaryKeyObj, jlong deriveMechanism, jbyteArray param, jbyteArray iv, jlong targetMechanism, jlong operation, jlong keySize) { jobject keyObj = NULL; PK11SlotInfo *slot=NULL; PK11SlotInfo *bestSlot = NULL; PK11SlotInfo *slotForKey = NULL; PK11SlotInfo *slotForSecondaryKey = NULL; PK11SlotInfo *finalSlot = NULL; PK11SlotInfo *finalSecondarySlot = NULL; PK11SlotInfo *finalBaseKeySlot = NULL; PK11SymKey *baseKey = NULL; PK11SymKey *bestBaseKey = NULL; PK11SymKey *finalBaseKey = NULL; PK11SymKey *newKey = NULL; PK11SymKey *secondaryKey = NULL; PK11SymKey *bestSecondaryKey = NULL; PK11SymKey *finalSecondaryKey = NULL; PK11SymKey *derivedKey = NULL; jbyte *paramValue = NULL; int paramLength = 0; jbyte *ivValue = NULL; int ivLength = 0; CK_OBJECT_HANDLE keyhandle = 0; CK_AES_CBC_ENCRYPT_DATA_PARAMS aes; CK_DES_CBC_ENCRYPT_DATA_PARAMS des; CK_KEY_DERIVATION_STRING_DATA string; SECItem paramsItem = { siBuffer, NULL, 0 }; PR_ASSERT(env!=NULL && this!=NULL); if( baseKeyObj == 0) { PR_fprintf(PR_STDOUT,"baseKeyObj can not be null!\n"); goto finish; } if( param != NULL) { JSS_RefByteArray(env, param, ¶mValue, ¶mLength); } if( iv != NULL) { JSS_RefByteArray(env, iv, &ivValue, &ivLength); } /* Set up the params data for the PK11_Derive family */ switch ( deriveMechanism ) { case CKM_DES_ECB_ENCRYPT_DATA: case CKM_DES3_ECB_ENCRYPT_DATA: case CKM_AES_ECB_ENCRYPT_DATA: case CKM_CAMELLIA_ECB_ENCRYPT_DATA: case CKM_SEED_ECB_ENCRYPT_DATA: /* Use CK_KEY_DERIVATION_STRING_DATA */ string.pData = (unsigned char *) paramValue; string.ulLen = paramLength; paramsItem.data = (void *) &string; paramsItem.len = sizeof(string); break; case CKM_DES_CBC_ENCRYPT_DATA: case CKM_DES3_CBC_ENCRYPT_DATA: /* Use CK_DES_CBC_ENCRYPT_DATA_PARAMS */ if( ivValue == NULL) { PR_fprintf(PR_STDOUT, "Need iv param for CKM_DES_CBC_ENCRYPT_DATA or CKM_DES3_CBC_ENCRYPT_DATA. \n"); goto finish; } if( ivLength != 8) { PR_fprintf(PR_STDOUT, "Need iv param for CKM_DES_CBC_ENCRYPT_DATA structure to be 8 bytes!. \n"); goto finish; } des.pData = (unsigned char *) paramValue; des.length = paramLength; PORT_Memcpy(des.iv,ivValue,ivLength); paramsItem.data = (void *) &des; paramsItem.len = sizeof(des); break; case CKM_AES_CBC_ENCRYPT_DATA: case CKM_CAMELLIA_CBC_ENCRYPT_DATA: case CKM_SEED_CBC_ENCRYPT_DATA: /* Use CK_AES_CBC_ENCRYPT_DATA_PARAMS */ if ( ivValue == NULL ) { PR_fprintf(PR_STDOUT, "Need iv param for CBC encrypt derive for AES, or CAMELLIA or SEED. \n"); goto finish; } if( ivLength != 16) { PR_fprintf(PR_STDOUT, "Need iv param for CK_AES_CBC_ENCRYPT_DATA_PARAMS structure to be 16 bytes!. \n"); goto finish; } aes.pData = (unsigned char *) paramValue; aes.length = paramLength; PORT_Memcpy(aes.iv,ivValue,ivLength); paramsItem.data = (void *) &aes; paramsItem.len = sizeof(aes); break; default: paramsItem.data = (unsigned char *) paramValue; paramsItem.len = paramLength; break; } /* Get slot */ if( JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS) { goto finish; } /* Get base key */ if( JSS_PK11_getSymKeyPtr(env, baseKeyObj, &baseKey) != PR_SUCCESS) { PR_fprintf(PR_STDOUT, "PK11SymmetricKeyDeriver.nativeDeriveSymKey: Unable to extract symmetric base key!"); goto finish; } /* Ask NSS what the best slot for the given mechanism */ bestSlot = PK11_GetBestSlot(deriveMechanism, NULL); if( bestSlot == NULL) { PR_fprintf(PR_STDOUT,"PK11SymmetricKeyDeriver.nativeDeriveSymKey: Can't find suitable slot for sym key derivation! \n"); goto finish; } slotForKey = PK11_GetSlotFromKey(baseKey); int keyOnRequestedSlot = 0; if(slotForKey != slot) { keyOnRequestedSlot = 0; } else { keyOnRequestedSlot = 1; finalBaseKeySlot = slot; } if ( PK11_DoesMechanism( slot, deriveMechanism)) { if ( keyOnRequestedSlot ) { finalBaseKey = baseKey; } else { bestBaseKey = PK11_MoveSymKey( slot, CKA_ENCRYPT, 0, PR_FALSE, baseKey ); if(bestBaseKey == NULL) { PR_fprintf(PR_STDOUT,"PK11SymmetricKeyDeriver.nativeDeriveSymKey: Can't move Base Key to requested slot!\n"); goto finish; } finalBaseKey = bestBaseKey; finalBaseKeySlot = slot; } } else { bestBaseKey = PK11_MoveSymKey( bestSlot, CKA_ENCRYPT, 0, PR_FALSE, baseKey ); if(bestBaseKey == NULL) { PR_fprintf(PR_STDOUT,"PK11SymmetricKeyDeriver.nativeDeriveSymKey: Can't move Base Key to best slot!\n"); goto finish; } finalBaseKey = bestBaseKey; finalBaseKeySlot = bestSlot; } /* Assume we want to do a concatenation family here */ if( secondaryKeyObj != NULL) { if( JSS_PK11_getSymKeyPtr(env, secondaryKeyObj, &secondaryKey) != PR_SUCCESS) { PR_fprintf(PR_STDOUT,"PK11SymmetricKeyDeriver.nativeDeriveSymKey: Can't find secondary sym key!\n"); goto finish; } /* Make sure the secondary key is in the proper slot to do concatenation */ slotForSecondaryKey = PK11_GetSlotFromKey( secondaryKey ); if( finalBaseKeySlot != slotForSecondaryKey ) { finalSecondaryKey = PK11_MoveSymKey (finalBaseKeySlot, CKA_ENCRYPT, 0, PR_FALSE, secondaryKey); if( finalSecondaryKey == NULL) { PR_fprintf(PR_STDOUT,"PK11SymmetricKeyDeriver.nativeDeriveSymKey, Problem moving secondary key to proper slot.\n"); goto finish; } } else { finalSecondaryKey = secondaryKey; } if( paramValue == NULL) { keyhandle = PK11_GetSymKeyHandle(finalSecondaryKey); if( keyhandle == 0) { PR_fprintf(PR_STDOUT,"PK11SymmetricKeyDeriver.nativeDeriveSymKey, can't get handle for secondary sym key.\n"); goto finish; } paramsItem.data=(unsigned char *) &keyhandle; paramsItem.len=sizeof(keyhandle); } else { PR_fprintf(PR_STDOUT,"PK11SymmetricKeyDeriver.nativeDeriveSymKey: incorrect input parameter provided!\n"); goto finish; } } derivedKey = PK11_Derive(finalBaseKey, deriveMechanism, ¶msItem, targetMechanism, operation, keySize); if(derivedKey == NULL) { PR_fprintf(PR_STDOUT, "ERROR: Can't derive symmetric key, error: %d \n",PR_GetError()); goto finish; } if ( (finalSlot = PK11_GetSlotFromKey(derivedKey )) != slot) { newKey = PK11_MoveSymKey ( slot, CKA_ENCRYPT, 0, PR_FALSE, derivedKey); if ( newKey == NULL ) { PR_fprintf(PR_STDOUT,"PK11SymmetricKeyDeriver.nativeDeriveSymKey: error moving key to original slot, return anyway. \n"); newKey = derivedKey; derivedKey = NULL; } } else { newKey = derivedKey; derivedKey = NULL; } keyObj = JSS_PK11_wrapSymKey(env, &newKey); finish: if ( bestBaseKey != NULL ) { PK11_FreeSymKey ( bestBaseKey ); bestBaseKey = NULL; } if ( bestSecondaryKey != NULL ) { PK11_FreeSymKey ( bestSecondaryKey ); bestSecondaryKey = NULL; } if ( derivedKey != NULL) { PK11_FreeSymKey ( derivedKey ); derivedKey = NULL; } if (bestSlot != NULL ) { PK11_FreeSlot(bestSlot); bestSlot = NULL; } if ( slotForKey != NULL ) { PK11_FreeSlot( slotForKey ); slotForKey = NULL; } if ( finalSlot != NULL ) { PK11_FreeSlot( finalSlot ); finalSlot = NULL; } if ( finalSecondarySlot != NULL ) { PK11_FreeSlot( finalSecondarySlot ); finalSecondarySlot = NULL; } if ( slotForSecondaryKey != NULL ) { PK11_FreeSlot( slotForSecondaryKey ); slotForSecondaryKey = NULL; } JSS_DerefByteArray(env, param, paramValue, JNI_ABORT); JSS_DerefByteArray(env, iv, ivValue, JNI_ABORT); if( keyObj == NULL) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Unable to derive symmetric key! " "failure!"); } return keyObj; } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11SymmetricKeyDeriver.java000066400000000000000000000130021412550063600263120ustar00rootroot00000000000000/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * 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 Services for Java. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.jss.pkcs11; import org.mozilla.jss.crypto.*; import java.security.InvalidKeyException; /*This operation is pkcs11 based only */ public class PK11SymmetricKeyDeriver implements SymmetricKeyDeriver { private PK11Token token = null; private SymmetricKey baseKey = null; private SymmetricKey secondaryKey = null; private long deriveMechanism = 0; private long targetMechanism = 0; private long operation = 0; private long keySize = 0; private byte[] param = null; private byte[] iv = null; public PK11SymmetricKeyDeriver(PK11Token token) { this.token = token; } /* Use with the encrypt type mechanisms Example: initDerive( symKey, (PKCS11Constants.CKM_DES3_ECB_ENCRYPT_DATA) 4354L, derivationData, null, PKCS11Constants.CKM_DES3_ECB, PKCS11Constants.CKA_DERIVE, 16); */ @Override public void initDerive(SymmetricKey baseKey, long deriveMech, byte[] param, byte[] iv, long targetMech, long operation, long keySize) throws InvalidKeyException { reset(); if(baseKey == null) { throw new InvalidKeyException("Key is null"); } this.baseKey = baseKey; this.deriveMechanism = deriveMech; this.targetMechanism = targetMech; this.operation = operation; if ( param != null) { this.param = new byte[param.length]; System.arraycopy(param,0,this.param,0,param.length); } if ( iv != null) { this.iv = new byte[iv.length]; System.arraycopy(iv,0,this.iv,0,iv.length); } this.keySize = keySize; } /* Use with key extraction and key concatanation mechanisms Example Extraction: param: byte array that has the bit position of where to extract initDerive( derivedKey, PKCS11Constants.CKM_EXTRACT_KEY_FROM_KEY,param,null, PKCS11Constants.CKA_ENCRYPT, PKCS11Constants.CKA_DERIVE,8); Example Concat: initDerive( baseSymKey,secondarySymKey, PKCS11Constants.CKM_CONCATENATE_BASE_AND_KEY,null,null, PKCS11Constants.CKM_DES3_ECB, PKCS11Constants.CKA_DERIVE,0); */ @Override public void initDerive(SymmetricKey baseKey, SymmetricKey secondaryKey, long deriveMech, byte[] param, byte[] iv, long targetMech, long operation, long keySize) throws InvalidKeyException { reset(); if ( baseKey == null || secondaryKey == null) { throw new InvalidKeyException("Key is null"); } initDerive(baseKey, deriveMech, param,iv,targetMech,operation,keySize); this.secondaryKey = secondaryKey; } @Override public SymmetricKey derive() throws TokenException { SymmetricKey result = deriveSymKey(this.baseKey,this.secondaryKey,this.deriveMechanism, this.param, this.iv, this.targetMechanism, this.operation,this.keySize); return result; } private SymmetricKey deriveSymKey(SymmetricKey baseKey, SymmetricKey secondaryKey, long deriveMechanism, byte[] param, byte[] iv, long targetMechanism, long operation, long keySize) throws TokenException, IllegalStateException { return nativeDeriveSymKey(token, baseKey, secondaryKey,deriveMechanism, param, iv, targetMechanism, operation, keySize); } public native SymmetricKey nativeDeriveSymKey(PK11Token token, SymmetricKey baseKey, SymmetricKey secondaryKey, long deriveMechanism, byte[] param, byte[] iv, long targetMechanism, long operation, long keySize); private void reset() { baseKey = null; secondaryKey = null; deriveMechanism = 0; targetMechanism = 0; operation = 0; keySize = 0; param = null; iv = null; } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11Token.c000066400000000000000000000742511412550063600227420ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "_jni/org_mozilla_jss_pkcs11_PK11Token.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "java_ids.h" #include "pk11util.h" #include #define ERRX 1 #define KEYTYPE_DSA_STRING "dsa" #define KEYTYPE_RSA_STRING "rsa" #define KEYTYPE_EC_STRING "ec" static CERTCertificateRequest* make_cert_request(JNIEnv *env, const char *subject, SECKEYPublicKey *pubk); static void GenerateCertRequest(JNIEnv *env, SECOidTag ktype, const char *subject, PK11SlotInfo *slot, unsigned char **b64request, void *params); /* these values are taken from PK11KeyPairGenerator.java */ #define DEFAULT_RSA_KEY_SIZE 2048 #define DEFAULT_RSA_PUBLIC_EXPONENT 0x10001 /*********************************************************************** * * J S S _ P K 1 1 _ w r a p P K 1 1 T o k e n * * Create a PK11Token object from a PKCS #11 slot. * * slot is a pointer to a PKCS #11 slot, which must not be NULL. It will * be eaten by the wrapper, so you can't use it after you call this. * * Returns a new PK11Token object, or NULL if an exception was thrown. */ jobject JSS_PK11_wrapPK11Token(JNIEnv *env, PK11SlotInfo **slot) { jclass tokenClass; jmethodID constructor; jbyteArray byteArray; jobject Token=NULL; jboolean internal; jboolean keyStorage; PK11SlotInfo *internalSlot = NULL; PR_ASSERT(env!=NULL && slot!=NULL && *slot!=NULL); internalSlot = PK11_GetInternalSlot(); internal = (*slot == internalSlot); keyStorage = PK11_IsInternalKeySlot(*slot); byteArray = JSS_ptrToByteArray(env, (void*)*slot); /* * Lookup the class and constructor */ tokenClass = (*env)->FindClass(env, PK11TOKEN_CLASS_NAME); if(tokenClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } constructor = (*env)->GetMethodID( env, tokenClass, PK11TOKEN_CONSTRUCTOR_NAME, PK11TOKEN_CONSTRUCTOR_SIG); if(constructor == NULL) { ASSERT_OUTOFMEM(env); goto finish; } /* Call the constructor */ Token = (*env)->NewObject(env, tokenClass, constructor, byteArray, internal, keyStorage); finish: if (Token == NULL) { PK11_FreeSlot(*slot); } if (internalSlot != NULL) { PK11_FreeSlot(internalSlot); } *slot = NULL; return Token; } /************************************************************************ * * P K 1 1 T o k e n . needs Login * * returns true if this token needs to be logged into before it can be used. */ JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_pkcs11_PK11Token_needsLogin (JNIEnv *env, jobject this) { PK11SlotInfo *slot; jboolean retval; PR_ASSERT(env!=NULL && this!=NULL); if(JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); /* an exception was thrown */ retval = JNI_FALSE; goto finish; } PR_ASSERT(slot != NULL); if(PK11_NeedLogin(slot) == PR_TRUE) { retval = JNI_TRUE; } else { retval = JNI_FALSE; } finish: return retval; } /************************************************************************ * * P K 1 1 T o k e n . i s L o g g e d I n * * Returns true if this token is logged in. */ JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_pkcs11_PK11Token_isLoggedIn (JNIEnv *env, jobject this) { PK11SlotInfo *slot; jboolean retval; PR_ASSERT(env!=NULL && this!=NULL); if(JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); /* an exception was thrown */ retval = JNI_FALSE; goto finish; } PR_ASSERT(slot != NULL); if(PK11_IsLoggedIn(slot, NULL) == PR_TRUE) { retval = JNI_TRUE; } else { retval = JNI_FALSE; } finish: return retval; } /************************************************************************ * * P K 1 1 T o k e n . n a t i v e L o g i n * * Attempts to login to the token with the given password callback. * Throws NotInitializedException if the token is not initialized. * Throws IncorrectPINException if the supplied PIN is incorrect. */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11Token_nativeLogin (JNIEnv *env, jobject this, jobject callback) { PK11SlotInfo *slot; PR_ASSERT(env!=NULL && this!=NULL && callback!=NULL); if(JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); /* an exception was thrown */ goto finish; } PR_ASSERT(slot != NULL); /* Is the token initialized? */ if(PK11_NeedUserInit(slot)) { JSS_nativeThrow( env, TOKEN_NOT_INITIALIZED_EXCEPTION ); goto finish; } if(PK11_Authenticate(slot, PR_TRUE /*loadCerts*/, (void*)callback) != SECSuccess) { JSS_nativeThrow(env, INCORRECT_PASSWORD_EXCEPTION); goto finish; } /* Success! */ finish: return; } /************************************************************************ * * P K 1 1 T o k e n . l o g o u t */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11Token_logout (JNIEnv *env, jobject this) { PK11SlotInfo *slot; PR_ASSERT(env!=NULL && this!=NULL); if( JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); /* an exception occurred */ goto finish; } PR_ASSERT(slot != NULL); if( PK11_Logout(slot) != SECSuccess) { JSS_nativeThrowMsg( env, TOKEN_EXCEPTION, "Unable to logout token" ); goto finish; } finish: return; } /************************************************************************ * * P K 1 1 T o k e n . g e t L o g i n M o d e * * Returns the login mode (ONE_TIME, TIMEOUT, EVERY_TIME) for this token. * These constants must sync with the ones defined in CryptoToken. */ #define ONE_TIME 0 #define TIMEOUT 1 #define EVERY_TIME 2 /************************************************************************ * * P K 1 1 T o k e n . g e t L o g i n M o d e * */ JNIEXPORT jint JNICALL Java_org_mozilla_jss_pkcs11_PK11Token_getLoginMode (JNIEnv *env, jobject this) { PK11SlotInfo *slot; jint mode=ONE_TIME; int askpw; int timeout; PR_ASSERT(env!=NULL && this!=NULL); if( JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } PR_ASSERT(slot!=NULL); PK11_GetSlotPWValues(slot, &askpw, &timeout); if(askpw == -1) { mode = EVERY_TIME; } else if(askpw == 0) { mode = ONE_TIME; } else if(askpw == 1) { mode = TIMEOUT; } else { JSS_throw(env, TOKEN_EXCEPTION); goto finish; } finish: return mode; } /************************************************************************ * * P K 1 1 T o k e n . g e t L o g i n T i m e o u t M i n u t e s */ JNIEXPORT jint JNICALL Java_org_mozilla_jss_pkcs11_PK11Token_getLoginTimeoutMinutes (JNIEnv *env, jobject this) { PK11SlotInfo *slot; int askpw; int timeout=0; PR_ASSERT(env!=NULL && this!=NULL); if( JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } PR_ASSERT(slot!=NULL); PK11_GetSlotPWValues(slot, &askpw, &timeout); finish: return timeout; } /************************************************************************ * * P K 1 1 T o k e n . s e t L o g i n M o d e * */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11Token_setLoginMode (JNIEnv *env, jobject this, jint mode) { PK11SlotInfo *slot; int askpw, timeout; PR_ASSERT(env!=NULL && this!=NULL); if( JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } PR_ASSERT(slot!=NULL); PK11_GetSlotPWValues(slot, &askpw, &timeout); if(mode == EVERY_TIME) { askpw = -1; } else if(mode == ONE_TIME) { askpw = 0; } else if(mode == TIMEOUT) { askpw = 1; } else { JSS_throw(env, TOKEN_EXCEPTION); goto finish; } PK11_SetSlotPWValues(slot, askpw, timeout); finish: ; } /************************************************************************ * * P K 1 1 T o k e n . s e t L o g i n T i m e o u t M i n u t e s * */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11Token_setLoginTimeoutMinutes (JNIEnv *env, jobject this, jint newTimeout) { PK11SlotInfo *slot; int askpw, timeout; PR_ASSERT(env!=NULL && this!=NULL); if( JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); return; } PR_ASSERT(slot!=NULL); PK11_GetSlotPWValues(slot, &askpw, &timeout); PK11_SetSlotPWValues(slot, askpw, newTimeout); } /************************************************************************ * * P K 1 1 T o k e n . i s P r e s e n t * * Returns true if this token is present in the slot */ JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_pkcs11_PK11Token_isPresent (JNIEnv *env, jobject this) { PK11SlotInfo *slot; jboolean retval; PR_ASSERT(env!=NULL && this!=NULL); if(JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); /* an exception was thrown */ retval = JNI_FALSE; goto finish; } PR_ASSERT(slot != NULL); if(PK11_IsPresent(slot) == PR_TRUE) { retval = JNI_TRUE; } else { retval = JNI_FALSE; } finish: return retval; } /************************************************************************ * * P K 1 1 T o k e n . P W I n i t a b l e * * Make sure this token can be initialized. Currently we only check the * internal module, since it can't be initialized more than once. * Presumably most tokens can have their PINs initialized arbitrarily * many times. */ JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_pkcs11_PK11Token_PWInitable (JNIEnv *env, jobject this) { PK11SlotInfo *slot=NULL; jboolean initable=JNI_FALSE; PR_ASSERT(env!=NULL && this!=NULL); /* * Convert Java objects to native objects */ if(JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); /* an exception was thrown */ goto finish; } PR_ASSERT(slot!=NULL); if (!PK11_IsInternalKeySlot(slot)) { /* We don't know about other tokens */ initable = JNI_TRUE; } else { if(PK11_NeedUserInit(slot)) { initable = JNI_TRUE; } else { /* Internal module only allows one init, after this you * need to do a changePIN */ initable = JNI_FALSE; } } finish: return initable; } /************************************************************************ * * P K 1 1 T o k e n . i n i t P a s s w o r d * */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11Token_initPassword (JNIEnv *env, jobject this, jbyteArray ssopw, jbyteArray userpw) { PK11SlotInfo *slot=NULL; char *szSsopw=NULL, *szUserpw=NULL; jboolean ssoIsCopy, userIsCopy; SECStatus initResult; PRErrorCode error; PR_ASSERT(env!=NULL && this!=NULL && ssopw!=NULL && userpw!=NULL); /* * Convert Java objects to native objects */ if(JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); /* an exception was thrown */ goto finish; } szSsopw = (char*) (*env)->GetByteArrayElements(env, ssopw, &ssoIsCopy); szUserpw = (char*) (*env)->GetByteArrayElements(env, userpw, &userIsCopy); PR_ASSERT(slot!=NULL && szSsopw!=NULL && szUserpw!=NULL); /* * If we're on the internal module, make sure we can still be * initialized. */ if (PK11_IsInternalKeySlot(slot) && !PK11_NeedUserInit(slot)) { JSS_nativeThrowMsg(env, ALREADY_INITIALIZED_EXCEPTION, "Netscape Internal Key Token is already initialized"); goto finish; } /* * Initialize the PIN */ initResult = PK11_InitPin(slot, szSsopw, szUserpw); if(initResult != SECSuccess) { error = PR_GetError(); } /* * Throw exception if an error occurred */ if(initResult != SECSuccess) { if(error == SEC_ERROR_BAD_PASSWORD) { JSS_nativeThrowMsg( env, INCORRECT_PASSWORD_EXCEPTION, "Incorrect security officer PIN" ); } else { JSS_nativeThrowMsg( env, TOKEN_EXCEPTION, "Unable to initialize PIN" ); } } finish: /* * Free native objects */ if (szSsopw && ssoIsCopy) { JSS_wipeCharArray(szSsopw); } JSS_DerefByteArray(env, ssopw, szSsopw, JNI_ABORT); if (szUserpw && userIsCopy) { JSS_wipeCharArray(szUserpw); } JSS_DerefByteArray(env, userpw, szUserpw, JNI_ABORT); return; } /************************************************************************ * * P K 1 1 T o k e n . p a s s w o r d I s I n i t i a l i z e d * */ JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_pkcs11_PK11Token_passwordIsInitialized (JNIEnv *env, jobject this) { PK11SlotInfo *slot=NULL; jboolean isInitialized = JNI_FALSE; PR_ASSERT(env!=NULL && this!=NULL); /* * Convert Java arguments to C */ if( JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } PR_ASSERT(slot != NULL); if (PK11_IsInternalKeySlot(slot)) { /* special case for our Key slot */ isInitialized = ! PK11_NeedPWInit(); } else { isInitialized = ! PK11_NeedUserInit(slot); } finish: return isInitialized; } /************************************************************************ * * P K 1 1 T o k e n . c h a n g e P a s s w o r d * */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11Token_changePassword (JNIEnv *env, jobject this, jbyteArray oldPIN, jbyteArray newPIN) { PK11SlotInfo *slot=NULL; char *szOldPIN=NULL, *szNewPIN=NULL; jboolean oldIsCopy, newIsCopy; SECStatus changeResult; PRErrorCode error; PR_ASSERT(env!=NULL && this!=NULL && oldPIN!=NULL && newPIN!=NULL); /* * Convert Java objects to native objects */ if(JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); /* an exception was thrown */ goto finish; } szOldPIN= (char*) (*env)->GetByteArrayElements(env, oldPIN, &oldIsCopy); szNewPIN= (char*) (*env)->GetByteArrayElements(env, newPIN, &newIsCopy); PR_ASSERT(slot!=NULL && szOldPIN!=NULL && szNewPIN!=NULL); /* * Change the PIN */ changeResult = PK11_ChangePW(slot, szOldPIN, szNewPIN); if(changeResult != SECSuccess) { error = PR_GetError(); } /* * Throw exception if an error occurred */ if(changeResult != SECSuccess) { if(error == SEC_ERROR_BAD_PASSWORD) { JSS_nativeThrowMsg( env, INCORRECT_PASSWORD_EXCEPTION, "Incorrect PIN" ); } else { JSS_nativeThrowMsg( env, TOKEN_EXCEPTION, "Unable to change PIN" ); } } finish: /* Free native objects */ if(szOldPIN && oldIsCopy) { JSS_wipeCharArray(szOldPIN); } JSS_DerefByteArray(env, oldPIN, szOldPIN, JNI_ABORT); if(szNewPIN && newIsCopy) { JSS_wipeCharArray(szNewPIN); } JSS_DerefByteArray(env, newPIN, szNewPIN, JNI_ABORT); return; } typedef enum { SSOPW, USERPW } pwType; /************************************************************************ * * p a s s w o r d I s C o r r e c t * * Checks the given password, which could be an SSO or a user password. * Returns JNI_TRUE if the password is correct, JNI_FALSE if it isn't, * and may throw an exception if something goes wrong on the token. */ static jboolean passwordIsCorrect (JNIEnv *env, jobject this, jbyteArray password, pwType type) { PK11SlotInfo *slot = NULL; char *pwBytes=NULL; jboolean isCopy; jboolean pwIsCorrect = JNI_FALSE; SECStatus status; int error; PR_ASSERT(env!=NULL && this!=NULL && password!=NULL); /* * Convert Java args to C */ if( JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } pwBytes = (char*) (*env)->GetByteArrayElements(env, password, &isCopy); PR_ASSERT(slot!=NULL && pwBytes != NULL); /* * Do the check */ if(type == SSOPW) { status = PK11_CheckSSOPassword(slot, pwBytes); } else { status = PK11_CheckUserPassword(slot, pwBytes); } if(status == SECSuccess) { pwIsCorrect = JNI_TRUE; } else { error = PR_GetError(); if(error == SEC_ERROR_BAD_PASSWORD) { /* just wrong password */ pwIsCorrect = JNI_FALSE; } else { /* some token problem */ JSS_nativeThrowMsg(env, TOKEN_EXCEPTION, "Unable to check password"); goto finish; } } finish: /* Free native objects */ if (pwBytes && isCopy) { JSS_wipeCharArray(pwBytes); } /* JNI_ABORT means don't copy back changes */ JSS_DerefByteArray(env, password, pwBytes, JNI_ABORT); return pwIsCorrect; } /************************************************************************ * * P K 1 1 T o k e n . u s e r P a s s w o r d I s C o r r e c t * */ JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_pkcs11_PK11Token_userPasswordIsCorrect (JNIEnv *env, jobject this, jbyteArray password) { return passwordIsCorrect(env, this, password, USERPW); } /************************************************************************ * * P K 1 1 T o k e n . S S O P a s s w o r d I s C o r r e c t * */ JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_pkcs11_PK11Token_SSOPasswordIsCorrect (JNIEnv *env, jobject this, jbyteArray password) { return passwordIsCorrect(env, this, password, SSOPW); } /************************************************************************ * * P K 1 1 T o k e n . g e t N a m e * * Returns the name of this token. */ JNIEXPORT jstring JNICALL Java_org_mozilla_jss_pkcs11_PK11Token_getName (JNIEnv *env, jobject this) { char *szName; PK11SlotInfo *slot; jstring name; jstring retval; PR_ASSERT(env!=NULL && this!=NULL); if(JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL ); /* an exception was thrown */ retval = NULL; goto finish; } PR_ASSERT(slot != NULL); szName = PK11_GetTokenName(slot); /* NULL C string converts to empty Java string */ if(szName == NULL) { szName = ""; } name = (*env)->NewStringUTF(env, szName); /* name could be NULL, if an OutOfMemoryError occurred. In that case, * we just return NULL and let the exception be thrown in Java */ #ifdef DEBUG if(name == NULL) { /* Make sure there is an exception before we return NULL */ PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); } #endif retval = name; finish: return retval; } /************************************************************************ * * T o k e n P r o x y . r e l e a s e N a t i v e R e s o u r c e s * * Free the PK11SlotInfo structure that underlies my token. */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_TokenProxy_releaseNativeResources (JNIEnv *env, jobject this) { PK11SlotInfo *slot = NULL; PR_ASSERT(env!=NULL && this!=NULL); if(JSS_getPtrFromProxy(env, this, (void**)&slot) != PR_SUCCESS) { PR_ASSERT( PR_FALSE ); goto finish; } /* * PK11Token never stores a null pointer in its TokenProxy member, * but PK11Cert may store a null pointer in its TokenProxy member. * (A temporary certificate has a null slot pointer.) */ if(slot != NULL) { /* this actually only frees the data structure if we were the last * reference to it */ PK11_FreeSlot(slot); } finish: return; } /************************************************************************ * * J S S _ g e t T o k e n S l o t P t r * * Retrieve the PK11SlotInfo pointer of the given token. * * tokenObject: A reference to a Java PK11Token * ptr: address of a PK11SlotInfo* that will be loaded with the PK11SlotInfo * pointer of the given token. * returns: PR_SUCCESS if the operation was successful, PR_FAILURE if an * exception was thrown. */ PRStatus JSS_PK11_getTokenSlotPtr(JNIEnv *env, jobject tokenObject, PK11SlotInfo **ptr) { PR_ASSERT(env != NULL && tokenObject != NULL && ptr != NULL); /* * Get the pointer from the PK11Token, which has a Token Proxy member */ PR_ASSERT(sizeof(PK11SlotInfo*) == sizeof(void*)); return JSS_getPtrFromProxyOwner(env, tokenObject, PK11TOKEN_PROXY_FIELD, PK11TOKEN_PROXY_SIG, (void**)ptr); } /********************************************************************** * * PK11Token.doesAlgorithm * */ JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_pkcs11_PK11Token_doesAlgorithm (JNIEnv *env, jobject this, jobject alg) { PK11SlotInfo *slot; CK_MECHANISM_TYPE mech; jboolean doesMech = JNI_FALSE; if( JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } PR_ASSERT(slot != NULL); mech = JSS_getPK11MechFromAlg(env, alg); /* not an assertion, some algorithms don't have Mechanism yet */ /*PR_ASSERT( mech != CKM_INVALID_MECHANISM ); */ if( PK11_DoesMechanism(slot, mech) == PR_TRUE) { doesMech = JNI_TRUE; } /* HACK...exceptions */ if( PK11_IsInternal(slot) && mech == CKM_PBA_SHA1_WITH_SHA1_HMAC ) { /* Although the internal slot doesn't actually do this mechanism, * we do it by hand in PK11KeyGenerator.c */ doesMech = JNI_TRUE; } finish: return doesMech; } /*********************************************************************** * * PK11Token.isWritable * */ JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_pkcs11_PK11Token_isWritable (JNIEnv *env, jobject this) { PK11SlotInfo *slot; if( JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { return JNI_FALSE; /* an exception was thrown, so it doesn't matter */ } PR_ASSERT(slot != NULL); return ! PK11_IsReadOnly(slot); } #define ZERO_SECITEM(item) {(item).len=0; (item).data=NULL;} int PK11_NumberObjectsFor(PK11SlotInfo*, CK_ATTRIBUTE*, int); /************************************************************************ * * P K 1 1 T o k e n . getCertRequest */ JNIEXPORT jstring JNICALL Java_org_mozilla_jss_pkcs11_PK11Token_generatePK10 (JNIEnv *env, jobject this, jstring subject, jint keysize, jstring keyType, jbyteArray P, jbyteArray Q, jbyteArray G) { PK11SlotInfo *slot; const char* c_subject=NULL; unsigned char *b64request=NULL; SECItem p, q, g; PQGParams *dsaParams=NULL; const char* c_keyType; SECOidTag signType = SEC_OID_UNKNOWN; PK11RSAGenParams rsaParams; void *params = NULL; PR_ASSERT(env!=NULL && this!=NULL); /* get keytype */ c_keyType = JSS_RefJString(env, keyType); if (0 == PL_strcasecmp(c_keyType, KEYTYPE_RSA_STRING)) { signType = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION; if( keysize == -1 ) { rsaParams.keySizeInBits = DEFAULT_RSA_KEY_SIZE; } else { rsaParams.keySizeInBits = keysize; } rsaParams.pe = DEFAULT_RSA_PUBLIC_EXPONENT; params = (void *)&rsaParams; } else if (0 == PL_strcasecmp(c_keyType, KEYTYPE_DSA_STRING)) { signType = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST; if (P==NULL || Q==NULL || G ==NULL) { /* shouldn't happen */ JSS_throw(env, INVALID_PARAMETER_EXCEPTION); } else { /* caller supplies PQG */ /* zero these so we can free them indiscriminately later */ ZERO_SECITEM(p); ZERO_SECITEM(q); ZERO_SECITEM(g); if( JSS_ByteArrayToOctetString(env, P, &p) || JSS_ByteArrayToOctetString(env, Q, &q) || JSS_ByteArrayToOctetString(env, G, &g) ) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); goto finish; } dsaParams = PK11_PQG_NewParams(&p, &q, &g); if(dsaParams == NULL) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } } params = (void *)dsaParams; } else if (0 == PL_strcasecmp(c_keyType, KEYTYPE_EC_STRING)) { signType = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST; /* get ec param */ } else { JSS_throw(env, INVALID_PARAMETER_EXCEPTION); } if( JSS_PK11_getTokenSlotPtr(env, this, &slot) != PR_SUCCESS) { PR_ASSERT( (*env)->ExceptionOccurred(env) != NULL); /* an exception occurred */ goto finish; } PR_ASSERT(slot != NULL); if(PK11_IsLoggedIn(slot, NULL) != PR_TRUE) { JSS_nativeThrowMsg(env, TOKEN_EXCEPTION, "token not logged in"); } /* get subject */ c_subject = JSS_RefJString(env, subject); /* call GenerateCertRequest() */ GenerateCertRequest(env, signType, c_subject, slot, &b64request, params); finish: /* release memory */ JSS_DerefJString(env, subject, c_subject); /* release memory */ JSS_DerefJString(env, keyType, c_keyType); if (signType == SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) { SECITEM_FreeItem(&p, PR_FALSE); SECITEM_FreeItem(&q, PR_FALSE); SECITEM_FreeItem(&g, PR_FALSE); PK11_PQG_DestroyParams(dsaParams); } if (b64request == NULL) { return NULL; } else { /* convert to String */ return (*env)->NewStringUTF(env, (const char *)b64request); } } /* * generate keypairs and further the request * the real thing will need keytype and pqg numbers (for DSA) */ void GenerateCertRequest(JNIEnv *env, SECOidTag signType, const char *subject, PK11SlotInfo *slot, unsigned char **b64request, void *params) { CERTCertificateRequest *req; SECKEYPrivateKey *privk = NULL; SECKEYPublicKey *pubk = NULL; SECStatus rv; PRArenaPool *arena; SECItem result_der, result; SECItem * VARIABLE_MAY_NOT_BE_USED blob; CK_MECHANISM_TYPE signMech; CK_MECHANISM_TYPE keygenMech; #ifdef DEBUG printf("in GenerateCertRequest(), subject=%s, ", subject); #endif /* * Use the tables to reduce the code of adding new * types of keys. */ signMech = PK11_AlgtagToMechanism(signType); if (signMech == CKM_INVALID_MECHANISM) { #ifdef DEBUG printf("Error getting KEYGEN Mechanism."); #endif } keygenMech = PK11_GetKeyGen(signMech); if( JSS_PK11_generateKeyPair(env, keygenMech, slot, &pubk, &privk, params, PR_FALSE, -1, -1) != SECSuccess) { #ifdef DEBUG printf("Error generating keypair."); #endif } #ifdef DEBUG printf("before make_cert_request"); #endif req = make_cert_request (env, subject, pubk); #ifdef DEBUG printf("after make_cert_request"); #endif if (req == NULL) { return; } result_der.len = 0; result_der.data = NULL; #ifdef DEBUG printf("before SEC_ASN1EncodeItem"); #endif /* der encode the request */ blob = SEC_ASN1EncodeItem(req->arena, &result_der, req, SEC_ASN1_GET(CERT_CertificateRequestTemplate)); /* sign the request */ arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if ( !arena ) { JSS_throw(env, OUT_OF_MEMORY_ERROR); return; } rv = SEC_DerSignData(arena, &result, result_der.data, result_der.len, privk, signType); if (rv) { JSS_nativeThrowMsg(env, TOKEN_EXCEPTION, "signing of data failed"); PORT_FreeArena(arena, PR_FALSE); return; } *b64request = (unsigned char*) BTOA_DataToAscii(result.data, result.len); PORT_FreeArena(arena, PR_FALSE); #ifdef DEBUG printf("data = %s\n", *b64request); #endif } /****************************************************************** * * m a k e _ c e r t _ r e q u e s t */ static CERTCertificateRequest* make_cert_request(JNIEnv *env, const char *subject, SECKEYPublicKey *pubk) { CERTName *subj = NULL; CERTSubjectPublicKeyInfo *spki = NULL; CERTCertificateRequest *req = NULL; /* Create info about public key */ spki = SECKEY_CreateSubjectPublicKeyInfo(pubk); if (!spki) { JSS_nativeThrowMsg(env, TOKEN_EXCEPTION, "unable to create subject public key"); goto finish; } subj = CERT_AsciiToName ((char *)subject); if(subj == NULL) { JSS_nativeThrowMsg(env, TOKEN_EXCEPTION, "Invalid data in certificate description"); goto finish; } /* Generate certificate request */ req = CERT_CreateCertificateRequest(subj, spki, 0); if (!req) { JSS_nativeThrowMsg(env, TOKEN_EXCEPTION, "unable to make certificate request"); goto finish; } #ifdef DEBUG printf("certificate request generated\n"); #endif finish: if (subj) { CERT_DestroyName(subj); } if (spki) { SECKEY_DestroySubjectPublicKeyInfo(spki); } return req; } JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_PK11Token_importPublicKey( JNIEnv *env, jobject tokenObj, jobject pubKeyObj, jboolean permanent) { PK11SlotInfo *slot; SECKEYPublicKey *pubKey = NULL; PR_ASSERT(env != NULL && tokenObj != NULL && pubKeyObj != NULL); if (JSS_PK11_getTokenSlotPtr(env, tokenObj, &slot) != PR_SUCCESS) { PR_ASSERT((*env)->ExceptionOccurred(env) != NULL); /* an exception was thrown */ return; } PR_ASSERT(slot != NULL); if (PK11_IsLoggedIn(slot, NULL) != PR_TRUE) { JSS_nativeThrowMsg(env, TOKEN_EXCEPTION, "token not logged in"); return; } if (PR_SUCCESS != JSS_PK11_getPubKeyPtr(env, pubKeyObj, &pubKey)) { return; // exception was thrown! } if (PK11_ImportPublicKey(slot, pubKey, permanent) == CK_INVALID_HANDLE) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "failed to import public key"); return; } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11Token.java000066400000000000000000000443631412550063600234420ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import java.security.InvalidKeyException; import java.security.InvalidParameterException; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import org.mozilla.jss.crypto.Algorithm; import org.mozilla.jss.crypto.AlreadyInitializedException; import org.mozilla.jss.crypto.Cipher; import org.mozilla.jss.crypto.CryptoStore; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.DigestAlgorithm; import org.mozilla.jss.crypto.EncryptionAlgorithm; import org.mozilla.jss.crypto.JSSMessageDigest; import org.mozilla.jss.crypto.KeyGenAlgorithm; import org.mozilla.jss.crypto.KeyGenerator; import org.mozilla.jss.crypto.KeyPairAlgorithm; import org.mozilla.jss.crypto.KeyPairGenerator; import org.mozilla.jss.crypto.KeyWrapAlgorithm; import org.mozilla.jss.crypto.KeyWrapper; import org.mozilla.jss.crypto.PQGParamGenException; import org.mozilla.jss.crypto.PQGParams; import org.mozilla.jss.crypto.SignatureAlgorithm; import org.mozilla.jss.crypto.SymmetricKey; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.util.IncorrectPasswordException; import org.mozilla.jss.util.NotImplementedException; import org.mozilla.jss.util.NullPasswordCallback; import org.mozilla.jss.util.Password; import org.mozilla.jss.util.PasswordCallback; import org.mozilla.jss.util.PasswordCallbackInfo; /** * A PKCS #11 token. Currently, these can only be obtained from the * CryptoManager class. * * @author nicolson * @version $Revision$ $Date$ * @see org.mozilla.jss.CryptoManager */ public final class PK11Token implements CryptoToken { protected TokenProxy tokenProxy; protected PK11Store cryptoStore; protected boolean mIsInternalCryptoToken; protected boolean mIsInternalKeyStorageToken; //////////////////////////////////////////////////// // exceptions //////////////////////////////////////////////////// /** * Thrown if the operation requires that the token be logged in, and it * isn't. */ static public class NotInitializedException extends IncorrectPasswordException { private static final long serialVersionUID = 1L; public NotInitializedException() {} public NotInitializedException(String mesg) {super(mesg);} } //////////////////////////////////////////////////// // public routines //////////////////////////////////////////////////// @Override public org.mozilla.jss.crypto.Signature getSignatureContext(SignatureAlgorithm algorithm) throws NoSuchAlgorithmException, TokenException { assert(algorithm!=null); return Tunnel.constructSignature( algorithm, new PK11Signature(this, algorithm) ); } @Override public JSSMessageDigest getDigestContext(DigestAlgorithm algorithm) throws NoSuchAlgorithmException, java.security.DigestException { if( ! doesAlgorithm(algorithm) ) { throw new NoSuchAlgorithmException(); } return new PK11MessageDigest(this, algorithm); } @Override public Cipher getCipherContext(EncryptionAlgorithm algorithm) throws NoSuchAlgorithmException, TokenException { if( ! doesAlgorithm(algorithm) ) { throw new NoSuchAlgorithmException( algorithm+" is not supported by this token"); } return new PK11Cipher(this, algorithm); } @Override public KeyGenerator getKeyGenerator(KeyGenAlgorithm algorithm) throws NoSuchAlgorithmException, TokenException { /* NSS is capable of finding the right token to do algorithm, so this call is prematurely bailing if( ! doesAlgorithm(algorithm) ) { throw new NoSuchAlgorithmException( algorithm+" is not supported by this token"); } */ return new PK11KeyGenerator(this, algorithm); } /** * Allows a SymmetricKey to be cloned on a different token. * * @exception SymmetricKey.NotExtractableException If the key material * cannot be extracted from the current token. * @exception InvalidKeyException If the owning token cannot process * the key to be cloned. */ @Override public SymmetricKey cloneKey(SymmetricKey key) throws SymmetricKey.NotExtractableException, InvalidKeyException, TokenException { return PK11KeyGenerator.clone(key, this); } @Override public PK11SymmetricKeyDeriver getSymmetricKeyDeriver() { return new PK11SymmetricKeyDeriver(this); } @Override public KeyWrapper getKeyWrapper(KeyWrapAlgorithm algorithm) throws NoSuchAlgorithmException, TokenException { /* NSS is capable of finding the right token to do algorithm, so this call is prematurely bailing if( ! doesAlgorithm(algorithm) ) { throw new NoSuchAlgorithmException( algorithm+" is not supported by this token"); } */ return new PK11KeyWrapper(this, algorithm); } public java.security.SecureRandom getRandomGenerator() throws NotImplementedException, TokenException { throw new NotImplementedException(); } @Override public org.mozilla.jss.crypto.KeyPairGenerator getKeyPairGenerator(KeyPairAlgorithm algorithm) throws NoSuchAlgorithmException, TokenException { assert(algorithm!=null); return new KeyPairGenerator(algorithm, new PK11KeyPairGenerator(this, algorithm)); } @Override public native boolean isLoggedIn() throws TokenException; @Override public native boolean needsLogin() throws TokenException; /** * Log into the token. If you are already logged in, this method has * no effect, even if the PIN is wrong. * * @param callback A callback to use to obtain the password, or a * Password object. * @exception NotInitializedException The token has not yet been * initialized. * @exception IncorrectPasswordException The specified password * was incorrect. */ @Override public void login(PasswordCallback callback) throws NotInitializedException, IncorrectPasswordException, TokenException { if(callback == null) { callback = new NullPasswordCallback(); } nativeLogin(callback); } protected native void nativeLogin(PasswordCallback callback) throws NotInitializedException, IncorrectPasswordException, TokenException; /** * @return true if the token is writable, false if it is read-only. * Writable tokens can have their keys generated on the internal token * and then moved out. */ public native boolean isWritable(); /** * Determines if the given token is present on the system. * This would return false, for example, for a smart card reader * that didn't have a card inserted. */ @Override public native boolean isPresent(); /** * Log out of the token. * * @exception TokenException If you are already logged in, or an * unspecified error occurs. */ @Override public native void logout() throws TokenException; @Override public native int getLoginMode() throws TokenException; @Override public native void setLoginMode(int mode) throws TokenException; @Override public native int getLoginTimeoutMinutes() throws TokenException; @Override public native void setLoginTimeoutMinutes(int timeoutMinutes) throws TokenException; /** * Determines whether this is a removable token. For example, a smart card * is removable, while the Netscape internal module and a hardware * accelerator card are not removable. * @return true if the token is removable, false otherwise. */ //public native boolean isRemovable(); /** * Initialize PIN. This sets the user's new PIN, using the current * security officer PIN for authentication. * * @param ssopwcb The security officer's current password callback. * @param userpwcb The user's new password callback. * @exception IncorrectPasswordException If the security officer PIN is * incorrect. * @exception AlreadyInitializedException If the password hasn't already * been set. * @exception TokenException If the PIN was already initialized, * or there was an unspecified error in the token. */ @Override public void initPassword(PasswordCallback ssopwcb, PasswordCallback userpwcb) throws IncorrectPasswordException, AlreadyInitializedException, TokenException { byte[] ssopwArray = null; byte[] userpwArray = null; Password ssopw=null; Password userpw=null; PasswordCallbackInfo pwcb = makePWCBInfo(); if(ssopwcb==null) { ssopwcb = new NullPasswordCallback(); } if(userpwcb==null) { userpwcb = new NullPasswordCallback(); } try { // Make sure the password hasn't already been set, doing special // checks for the internal module if(!PWInitable()) { throw new AlreadyInitializedException(); } // Verify the SSO Password, except on internal module if( isInternalKeyStorageToken() ) { ssopwArray = new byte[] {0}; } else { ssopw = ssopwcb.getPasswordFirstAttempt(pwcb); ssopwArray = Tunnel.getPasswordByteCopy(ssopw); while( ! SSOPasswordIsCorrect(ssopwArray) ) { Password.wipeBytes(ssopwArray); ssopw.clear(); ssopw = ssopwcb.getPasswordAgain(pwcb); ssopwArray = Tunnel.getPasswordByteCopy(ssopw); } } // Now change the PIN userpw = userpwcb.getPasswordFirstAttempt(pwcb); userpwArray = Tunnel.getPasswordByteCopy(userpw); initPassword(ssopwArray, userpwArray); } catch (PasswordCallback.GiveUpException e) { throw new IncorrectPasswordException(e.toString()); } finally { // zero-out the arrays if(ssopwArray != null) { Password.wipeBytes(ssopwArray); } if(ssopw != null) { ssopw.clear(); } if(userpwArray != null) { Password.wipeBytes(userpwArray); } if(userpw != null) { userpw.clear(); } } } /** * Make sure the PIN can be initialized. This is mainly to check the * internal module. */ protected native boolean PWInitable() throws TokenException; protected native boolean SSOPasswordIsCorrect(byte[] ssopw) throws TokenException, AlreadyInitializedException; protected native void initPassword(byte[] ssopw, byte[] userpw) throws IncorrectPasswordException, AlreadyInitializedException, TokenException; /** * Determine whether the token has been initialized yet. */ @Override public native boolean passwordIsInitialized() throws TokenException; /** * Change password. This changes the user's PIN after it has already * been initialized. * * @param oldPINcb The user's old PIN callback. * @param newPINcb The new PIN callback. * @exception IncorrectPasswordException If the old PIN is incorrect. * @exception TokenException If some other error occurs on the token. * */ @Override public void changePassword(PasswordCallback oldPINcb, PasswordCallback newPINcb) throws IncorrectPasswordException, TokenException { byte[] oldPW = null; byte[] newPW = null; Password oldPIN=null; Password newPIN=null; PasswordCallbackInfo pwcb = makePWCBInfo(); if(oldPINcb==null) { oldPINcb = new NullPasswordCallback(); } if(newPINcb==null) { newPINcb = new NullPasswordCallback(); } try { // Verify the old password oldPIN = oldPINcb.getPasswordFirstAttempt(pwcb); oldPW = Tunnel.getPasswordByteCopy(oldPIN); if( ! userPasswordIsCorrect(oldPW) ) { do { Password.wipeBytes(oldPW); oldPIN.clear(); oldPIN = oldPINcb.getPasswordAgain(pwcb); oldPW = Tunnel.getPasswordByteCopy(oldPIN); } while( ! userPasswordIsCorrect(oldPW) ); } // Now change the PIN newPIN = newPINcb.getPasswordFirstAttempt(pwcb); newPW = Tunnel.getPasswordByteCopy(newPIN); changePassword(oldPW, newPW); } catch (PasswordCallback.GiveUpException e) { throw new IncorrectPasswordException(e.toString()); } finally { if(oldPW != null) { Password.wipeBytes(oldPW); } if(oldPIN != null) { oldPIN.clear(); } if(newPW != null) { Password.wipeBytes(newPW); } if(newPIN != null) { newPIN.clear(); } } } protected PasswordCallbackInfo makePWCBInfo() { return new TokenCallbackInfo(getName()); } /** * Check the given password, return true if it's right, false if it's * wrong. */ protected native boolean userPasswordIsCorrect(byte[] pw) throws TokenException; /** * Change the password on the token from the old one to the new one. */ protected native void changePassword(byte[] oldPIN, byte[] newPIN) throws IncorrectPasswordException, TokenException; @Override public native String getName(); public java.security.Provider getProvider() { throw new RuntimeException("PK11Token.getProvider() is not yet implemented"); } @Override public CryptoStore getCryptoStore() { return cryptoStore; } /** * Determines whether this token is capable of performing the given * PKCS #11 mechanism. */ /* public boolean doesMechanism(Mechanism mech) { return doesMechanismNative(mech.getValue()); } */ /** * Deep-comparison operator. * * @return true if these tokens point to the same underlying native token. * false otherwise, or if compare is null. */ @Override public boolean equals(Object obj) { if(obj==null) { return false; } else { if( ! (obj instanceof PK11Token) ) { return false; } return tokenProxy.equals(((PK11Token)obj).tokenProxy); } } //protected native boolean doesMechanismNative(int mech); /** * Determines whether this token is capable of performing the given * algorithm. */ @Override public native boolean doesAlgorithm(Algorithm alg); /** * Generates a PKCS#10 certificate request including Begin/End brackets * @param subject subject dn of the certificate * @param keysize size of the key * @param keyType "rsa" or "dsa" * @param P The DSA prime parameter * @param Q The DSA sub-prime parameter * @param G The DSA base parameter * @return String that represents a PKCS#10 b64 encoded blob with * begin/end brackets */ @Override public String generateCertRequest(String subject, int keysize, String keyType, byte[] P, byte[] Q, byte[] G) throws TokenException, InvalidParameterException, PQGParamGenException { if (keyType.equalsIgnoreCase("dsa")) { if ((P == null) && (Q == null) && (G == null)) { PQGParams pqg; try { pqg = PQGParams.generate(keysize); } catch (PQGParamGenException e) { throw e; } byte[] p = PQGParams.BigIntegerToUnsignedByteArray(pqg.getP()); byte[] q = PQGParams.BigIntegerToUnsignedByteArray(pqg.getQ()); byte[] g = PQGParams.BigIntegerToUnsignedByteArray(pqg.getG()); P = p; Q = q; G = g; String pk10String; try { pk10String = generatePK10(subject, keysize, keyType, p, q, g); } catch (TokenException e) { throw e; } catch (InvalidParameterException e) { throw e; } return ("-----BEGIN NEW CERTIFICATE REQUEST-----\n"+ pk10String + "\n-----END NEW CERTIFICATE REQUEST-----"); } else if ((P == null) || (Q == null) || (G == null)) { throw new InvalidParameterException("need all P, Q, and G"); } } String pk10String; try { pk10String = generatePK10(subject, keysize, keyType, P, Q, G); } catch (TokenException e) { throw e; } catch (InvalidParameterException e) { throw e; } return ("-----BEGIN NEW CERTIFICATE REQUEST-----\n"+ pk10String + "\n-----END NEW CERTIFICATE REQUEST-----"); } protected native String generatePK10(String subject, int keysize, String keyType, byte[] P, byte[] Q, byte[] G) throws TokenException, InvalidParameterException; //////////////////////////////////////////////////// // construction and finalization //////////////////////////////////////////////////// /* * Default constructor should never be called. */ protected PK11Token() { assert(false); } /** * Creates a new PK11Token. Should only be called from PK11Token's * native code. * @param pointer A byte array containing a pointer to a PKCS #11 slot. */ protected PK11Token(byte[] pointer, boolean internal, boolean keyStorage) { assert(pointer!=null); tokenProxy = new TokenProxy(pointer); mIsInternalCryptoToken = internal; mIsInternalKeyStorageToken = keyStorage; cryptoStore = new PK11Store(tokenProxy); } /* protected PK11Token(TokenProxy proxy) { assert(proxy!=null); this.tokenProxy = proxy; } */ public TokenProxy getProxy() { return tokenProxy; } /** * @return true if this is the internal token used for bulk crypto. */ public boolean isInternalCryptoToken() { return mIsInternalCryptoToken; } /** * @return true if this is the internal key storage token. */ public boolean isInternalKeyStorageToken() { return mIsInternalKeyStorageToken; } @Override public native void importPublicKey( PublicKey pubKey, boolean permanent) throws TokenException; } /** * This class just hard-wires the type to be TOKEN so we don't have to mess * with Java constants in native code. */ class TokenCallbackInfo extends PasswordCallbackInfo { public TokenCallbackInfo(String name) { super(name, TOKEN); } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PK11TokenCert.java000066400000000000000000000013301412550063600242430ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import org.mozilla.jss.crypto.*; /** * A user certificate that lives on a PKCS #11 token. */ public final class PK11TokenCert extends PK11Cert implements TokenCertificate { @Override public byte[] getUniqueID() { return super.getUniqueID(); } @Override public CryptoToken getOwningToken() { return super.getOwningToken(); } PK11TokenCert(byte[] certPtr, byte[] slotPtr, String nickname) { super(certPtr, slotPtr, nickname); } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/PKCS11Constants.java000066400000000000000000007220671412550063600245700ustar00rootroot00000000000000/** * PKCS11Constants.java - part of the JSS project * Copyright (C) 2018 Red Hat, Inc. * * This file is automatically generated (tools/build_pkcs11_constants.py) * from the contents of NSS's pkcs11t.h and pkcs11n.h headers. This * replaces the sun.security.pkcs11.wrapper.PKCS11Constants interface * which was removed from public visibility in JDK 9 due to the * introduction of modules. * * For more information, please see the documentation under * jss/docs/pkcs11_constants.md. * * Below are the copyright statements for the sourced files: */ /* Copyright statements from /usr/include/nss3/pkcs11t.h */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* License to copy and use this software is granted provided that it is * identified as "RSA Security Inc. PKCS #11 Cryptographic Token Interface * (Cryptoki)" in all material mentioning or referencing this software. * License is also granted to make and use derivative works provided that * such works are identified as "derived from the RSA Security Inc. PKCS #11 * Cryptographic Token Interface (Cryptoki)" in all material mentioning or * referencing the derived work. * RSA Security Inc. makes no representations concerning either the * merchantability of this software or the suitability of this software for * any particular purpose. It is provided "as is" without express or implied * warranty of any kind. */ /* Copyright statements from /usr/include/nss3/pkcs11n.h */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; public interface PKCS11Constants { /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_TRUE = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_FALSE = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_NULL_PTR = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_EFFECTIVELY_INFINITE = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_INVALID_HANDLE = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKN_SURRENDER = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_TOKEN_PRESENT = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_REMOVABLE_DEVICE = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_HW_SLOT = 0x00000004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_RNG = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_WRITE_PROTECTED = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_LOGIN_REQUIRED = 0x00000004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_USER_PIN_INITIALIZED = 0x00000008L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_RESTORE_KEY_NOT_NEEDED = 0x00000020L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_CLOCK_ON_TOKEN = 0x00000040L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_PROTECTED_AUTHENTICATION_PATH = 0x00000100L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_DUAL_CRYPTO_OPERATIONS = 0x00000200L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_TOKEN_INITIALIZED = 0x00000400L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_SECONDARY_AUTHENTICATION = 0x00000800L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_USER_PIN_COUNT_LOW = 0x00010000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_USER_PIN_FINAL_TRY = 0x00020000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_USER_PIN_LOCKED = 0x00040000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_USER_PIN_TO_BE_CHANGED = 0x00080000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_SO_PIN_COUNT_LOW = 0x00100000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_SO_PIN_FINAL_TRY = 0x00200000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_SO_PIN_LOCKED = 0x00400000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_SO_PIN_TO_BE_CHANGED = 0x00800000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_ERROR_STATE = 0x01000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKU_SO = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKU_USER = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKU_CONTEXT_SPECIFIC = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKS_RO_PUBLIC_SESSION = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKS_RO_USER_FUNCTIONS = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKS_RW_PUBLIC_SESSION = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKS_RW_USER_FUNCTIONS = 0x00000003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKS_RW_SO_FUNCTIONS = 0x00000004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_RW_SESSION = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_SERIAL_SESSION = 0x00000004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKO_DATA = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKO_CERTIFICATE = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKO_PUBLIC_KEY = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKO_PRIVATE_KEY = 0x00000003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKO_SECRET_KEY = 0x00000004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKO_HW_FEATURE = 0x00000005L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKO_DOMAIN_PARAMETERS = 0x00000006L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKO_MECHANISM = 0x00000007L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKO_PROFILE = 0x00000009L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKO_VENDOR_DEFINED = 0x80000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKP_INVALID_ID = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKP_BASELINE_PROVIDER = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKP_EXTENDED_PROVIDER = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKP_AUTHENTICATION_TOKEN = 0x00000003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKP_PUBLIC_CERTIFICATES_TOKEN = 0x00000004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKP_VENDOR_DEFINED = 0x80000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKH_MONOTONIC_COUNTER = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKH_CLOCK = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKH_USER_INTERFACE = 0x00000003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKH_VENDOR_DEFINED = 0x80000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_RSA = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_DSA = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_DH = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_ECDSA = 0x00000003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_EC = 0x00000003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_X9_42_DH = 0x00000004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_KEA = 0x00000005L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_GENERIC_SECRET = 0x00000010L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_RC2 = 0x00000011L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_RC4 = 0x00000012L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_DES = 0x00000013L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_DES2 = 0x00000014L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_DES3 = 0x00000015L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_CAST = 0x00000016L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_CAST3 = 0x00000017L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_CAST5 = 0x00000018L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_CAST128 = 0x00000018L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_RC5 = 0x00000019L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_IDEA = 0x0000001AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_SKIPJACK = 0x0000001BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_BATON = 0x0000001CL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_JUNIPER = 0x0000001DL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_CDMF = 0x0000001EL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_AES = 0x0000001FL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_BLOWFISH = 0x00000020L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_TWOFISH = 0x00000021L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_CAMELLIA = 0x00000025L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_SEED = 0x0000002FL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_ARIA = 0x00000026L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_MD5_HMAC = 0x00000027L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_SHA_1_HMAC = 0x00000028L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_RIPEMD128_HMAC = 0x00000029L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_RIPEMD160_HMAC = 0x0000002AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_SHA256_HMAC = 0x0000002BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_SHA384_HMAC = 0x0000002CL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_SHA512_HMAC = 0x0000002DL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_SHA224_HMAC = 0x0000002EL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_GOSTR3410 = 0x00000030L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_GOSTR3411 = 0x00000031L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_GOST28147 = 0x00000032L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_CHACHA20 = 0x00000033L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_POLY1305 = 0x00000034L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_AES_XTS = 0x00000035L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_SHA3_224_HMAC = 0x00000036L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_SHA3_256_HMAC = 0x00000037L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_SHA3_384_HMAC = 0x00000038L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_SHA3_512_HMAC = 0x00000039L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_BLAKE2B_160_HMAC = 0x0000003AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_BLAKE2B_256_HMAC = 0x0000003BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_BLAKE2B_384_HMAC = 0x0000003CL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_BLAKE2B_512_HMAC = 0x0000003DL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_SALSA20 = 0x0000003EL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_X2RATCHET = 0x0000003FL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_EC_EDWARDS = 0x00000040L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_EC_MONTGOMERY = 0x00000041L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_HKDF = 0x00000042L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_SHA512_224_HMAC = 0x00000043L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_SHA512_256_HMAC = 0x00000044L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_SHA512_T_HMAC = 0x00000045L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_VENDOR_DEFINED = 0x80000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKC_X_509 = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKC_X_509_ATTR_CERT = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKC_WTLS = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKC_VENDOR_DEFINED = 0x80000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_CERTIFICATE_CATEGORY_UNSPECIFIED = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_CERTIFICATE_CATEGORY_TOKEN_USER = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_CERTIFICATE_CATEGORY_AUTHORITY = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_CERTIFICATE_CATEGORY_OTHER_ENTITY = 0x00000003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_SECURITY_DOMAIN_UNSPECIFIED = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_SECURITY_DOMAIN_MANUFACTURER = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_SECURITY_DOMAIN_OPERATOR = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_SECURITY_DOMAIN_THIRD_PARTY = 0x00000003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_OTP_FORMAT_DECIMAL = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_OTP_FORMAT_HEXADECIMAL = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_OTP_FORMAT_ALPHANUMERIC = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_OTP_FORMAT_BINARY = 0x00000003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_OTP_PARAM_IGNORED = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_OTP_PARAM_OPTIONAL = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_OTP_PARAM_MANDATORY = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_ARRAY_ATTRIBUTE = 0x40000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_CLASS = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_TOKEN = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_PRIVATE = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_LABEL = 0x00000003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_APPLICATION = 0x00000010L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_VALUE = 0x00000011L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_OBJECT_ID = 0x00000012L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_CERTIFICATE_TYPE = 0x00000080L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_ISSUER = 0x00000081L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_SERIAL_NUMBER = 0x00000082L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_AC_ISSUER = 0x00000083L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_OWNER = 0x00000084L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_ATTR_TYPES = 0x00000085L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_TRUSTED = 0x00000086L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_CERTIFICATE_CATEGORY = 0x00000087L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_JAVA_MIDP_SECURITY_DOMAIN = 0x00000088L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_URL = 0x00000089L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_HASH_OF_SUBJECT_PUBLIC_KEY = 0x0000008AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_HASH_OF_ISSUER_PUBLIC_KEY = 0x0000008BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_CHECK_VALUE = 0x00000090L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_KEY_TYPE = 0x00000100L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_SUBJECT = 0x00000101L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_ID = 0x00000102L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_SENSITIVE = 0x00000103L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_ENCRYPT = 0x00000104L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_DECRYPT = 0x00000105L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_WRAP = 0x00000106L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_UNWRAP = 0x00000107L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_SIGN = 0x00000108L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_SIGN_RECOVER = 0x00000109L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_VERIFY = 0x0000010AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_VERIFY_RECOVER = 0x0000010BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_DERIVE = 0x0000010CL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_START_DATE = 0x00000110L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_END_DATE = 0x00000111L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_MODULUS = 0x00000120L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_MODULUS_BITS = 0x00000121L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_PUBLIC_EXPONENT = 0x00000122L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_PRIVATE_EXPONENT = 0x00000123L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_PRIME_1 = 0x00000124L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_PRIME_2 = 0x00000125L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_EXPONENT_1 = 0x00000126L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_EXPONENT_2 = 0x00000127L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_COEFFICIENT = 0x00000128L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_PUBLIC_KEY_INFO = 0x00000129L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_PRIME = 0x00000130L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_SUBPRIME = 0x00000131L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_BASE = 0x00000132L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_PRIME_BITS = 0x00000133L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_SUBPRIME_BITS = 0x00000134L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_SUB_PRIME_BITS = 0x00000134L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_VALUE_BITS = 0x00000160L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_VALUE_LEN = 0x00000161L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_EXTRACTABLE = 0x00000162L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_LOCAL = 0x00000163L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_NEVER_EXTRACTABLE = 0x00000164L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_ALWAYS_SENSITIVE = 0x00000165L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_KEY_GEN_MECHANISM = 0x00000166L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_MODIFIABLE = 0x00000170L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_COPYABLE = 0x00000171L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_DESTROYABLE = 0x00000172L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_ECDSA_PARAMS = 0x00000180L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_EC_PARAMS = 0x00000180L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_EC_POINT = 0x00000181L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_SECONDARY_AUTH = 0x00000200L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_AUTH_PIN_FLAGS = 0x00000201L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_ALWAYS_AUTHENTICATE = 0x00000202L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_WRAP_WITH_TRUSTED = 0x00000210L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_WRAP_TEMPLATE = 0x40000211L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_UNWRAP_TEMPLATE = 0x40000212L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_DERIVE_TEMPLATE = 0x40000213L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_OTP_FORMAT = 0x00000220L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_OTP_LENGTH = 0x00000221L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_OTP_TIME_INTERVAL = 0x00000222L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_OTP_USER_FRIENDLY_MODE = 0x00000223L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_OTP_CHALLENGE_REQUIREMENT = 0x00000224L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_OTP_TIME_REQUIREMENT = 0x00000225L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_OTP_COUNTER_REQUIREMENT = 0x00000226L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_OTP_PIN_REQUIREMENT = 0x00000227L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_OTP_COUNTER = 0x0000022EL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_OTP_TIME = 0x0000022FL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_OTP_USER_IDENTIFIER = 0x0000022AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_OTP_SERVICE_IDENTIFIER = 0x0000022BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_OTP_SERVICE_LOGO = 0x0000022CL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_OTP_SERVICE_LOGO_TYPE = 0x0000022DL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_GOSTR3410_PARAMS = 0x00000250L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_GOSTR3411_PARAMS = 0x00000251L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_GOST28147_PARAMS = 0x00000252L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_HW_FEATURE_TYPE = 0x00000300L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_RESET_ON_INIT = 0x00000301L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_HAS_RESET = 0x00000302L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_PIXEL_X = 0x00000400L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_PIXEL_Y = 0x00000401L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_RESOLUTION = 0x00000402L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_CHAR_ROWS = 0x00000403L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_CHAR_COLUMNS = 0x00000404L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_COLOR = 0x00000405L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_BITS_PER_PIXEL = 0x00000406L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_CHAR_SETS = 0x00000480L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_ENCODING_METHODS = 0x00000481L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_MIME_TYPES = 0x00000482L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_MECHANISM_TYPE = 0x00000500L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_REQUIRED_CMS_ATTRIBUTES = 0x00000501L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_DEFAULT_CMS_ATTRIBUTES = 0x00000502L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_SUPPORTED_CMS_ATTRIBUTES = 0x00000503L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_ALLOWED_MECHANISMS = 0x40000600L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_PROFILE_ID = 0x00000601L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_X2RATCHET_BAG = 0x00000602L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_X2RATCHET_BAGSIZE = 0x00000603L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_X2RATCHET_BOBS1STMSG = 0x00000604L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_X2RATCHET_CKR = 0x00000605L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_X2RATCHET_CKS = 0x00000606L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_X2RATCHET_DHP = 0x00000607L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_X2RATCHET_DHR = 0x00000608L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_X2RATCHET_DHS = 0x00000609L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_X2RATCHET_HKR = 0x0000060AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_X2RATCHET_HKS = 0x0000060BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_X2RATCHET_ISALICE = 0x0000060CL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_X2RATCHET_NHKR = 0x0000060DL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_X2RATCHET_NHKS = 0x0000060EL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_X2RATCHET_NR = 0x0000060FL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_X2RATCHET_NS = 0x00000610L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_X2RATCHET_PNS = 0x00000611L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_X2RATCHET_RK = 0x00000612L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKA_VENDOR_DEFINED = 0x80000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RSA_PKCS_KEY_PAIR_GEN = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RSA_PKCS = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RSA_9796 = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RSA_X_509 = 0x00000003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_MD2_RSA_PKCS = 0x00000004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_MD5_RSA_PKCS = 0x00000005L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA1_RSA_PKCS = 0x00000006L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RIPEMD128_RSA_PKCS = 0x00000007L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RIPEMD160_RSA_PKCS = 0x00000008L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RSA_PKCS_OAEP = 0x00000009L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RSA_X9_31_KEY_PAIR_GEN = 0x0000000AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RSA_X9_31 = 0x0000000BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA1_RSA_X9_31 = 0x0000000CL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RSA_PKCS_PSS = 0x0000000DL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA1_RSA_PKCS_PSS = 0x0000000EL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DSA_KEY_PAIR_GEN = 0x00000010L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DSA = 0x00000011L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DSA_SHA1 = 0x00000012L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DSA_SHA224 = 0x00000013L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DSA_SHA256 = 0x00000014L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DSA_SHA384 = 0x00000015L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DSA_SHA512 = 0x00000016L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DSA_SHA3_224 = 0x00000018L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DSA_SHA3_256 = 0x00000019L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DSA_SHA3_384 = 0x0000001AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DSA_SHA3_512 = 0x0000001BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DH_PKCS_KEY_PAIR_GEN = 0x00000020L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DH_PKCS_DERIVE = 0x00000021L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_X9_42_DH_KEY_PAIR_GEN = 0x00000030L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_X9_42_DH_DERIVE = 0x00000031L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_X9_42_DH_HYBRID_DERIVE = 0x00000032L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_X9_42_MQV_DERIVE = 0x00000033L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA256_RSA_PKCS = 0x00000040L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA384_RSA_PKCS = 0x00000041L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512_RSA_PKCS = 0x00000042L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA256_RSA_PKCS_PSS = 0x00000043L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA384_RSA_PKCS_PSS = 0x00000044L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512_RSA_PKCS_PSS = 0x00000045L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA224_RSA_PKCS = 0x00000046L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA224_RSA_PKCS_PSS = 0x00000047L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512_224 = 0x00000048L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512_224_HMAC = 0x00000049L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512_224_HMAC_GENERAL = 0x0000004AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512_224_KEY_DERIVATION = 0x0000004BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512_256 = 0x0000004CL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512_256_HMAC = 0x0000004DL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512_256_HMAC_GENERAL = 0x0000004EL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512_256_KEY_DERIVATION = 0x0000004FL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512_T = 0x00000050L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512_T_HMAC = 0x00000051L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512_T_HMAC_GENERAL = 0x00000052L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512_T_KEY_DERIVATION = 0x00000053L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_256_RSA_PKCS = 0x00000060L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_384_RSA_PKCS = 0x00000061L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_512_RSA_PKCS = 0x00000062L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_256_RSA_PKCS_PSS = 0x00000063L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_384_RSA_PKCS_PSS = 0x00000064L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_512_RSA_PKCS_PSS = 0x00000065L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_224_RSA_PKCS = 0x00000066L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_224_RSA_PKCS_PSS = 0x00000067L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RC2_KEY_GEN = 0x00000100L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RC2_ECB = 0x00000101L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RC2_CBC = 0x00000102L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RC2_MAC = 0x00000103L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RC2_MAC_GENERAL = 0x00000104L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RC2_CBC_PAD = 0x00000105L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RC4_KEY_GEN = 0x00000110L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RC4 = 0x00000111L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DES_KEY_GEN = 0x00000120L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DES_ECB = 0x00000121L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DES_CBC = 0x00000122L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DES_MAC = 0x00000123L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DES_MAC_GENERAL = 0x00000124L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DES_CBC_PAD = 0x00000125L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DES2_KEY_GEN = 0x00000130L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DES3_KEY_GEN = 0x00000131L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DES3_ECB = 0x00000132L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DES3_CBC = 0x00000133L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DES3_MAC = 0x00000134L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DES3_MAC_GENERAL = 0x00000135L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DES3_CBC_PAD = 0x00000136L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CDMF_KEY_GEN = 0x00000140L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CDMF_ECB = 0x00000141L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CDMF_CBC = 0x00000142L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CDMF_MAC = 0x00000143L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CDMF_MAC_GENERAL = 0x00000144L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CDMF_CBC_PAD = 0x00000145L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DES_OFB64 = 0x00000150L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DES_OFB8 = 0x00000151L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DES_CFB64 = 0x00000152L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DES_CFB8 = 0x00000153L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_MD2 = 0x00000200L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_MD2_HMAC = 0x00000201L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_MD2_HMAC_GENERAL = 0x00000202L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_MD5 = 0x00000210L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_MD5_HMAC = 0x00000211L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_MD5_HMAC_GENERAL = 0x00000212L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA_1 = 0x00000220L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA_1_HMAC = 0x00000221L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA_1_HMAC_GENERAL = 0x00000222L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RIPEMD128 = 0x00000230L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RIPEMD128_HMAC = 0x00000231L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RIPEMD128_HMAC_GENERAL = 0x00000232L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RIPEMD160 = 0x00000240L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RIPEMD160_HMAC = 0x00000241L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RIPEMD160_HMAC_GENERAL = 0x00000242L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA256 = 0x00000250L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA256_HMAC = 0x00000251L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA256_HMAC_GENERAL = 0x00000252L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA384 = 0x00000260L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA384_HMAC = 0x00000261L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA384_HMAC_GENERAL = 0x00000262L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512 = 0x00000270L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512_HMAC = 0x00000271L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512_HMAC_GENERAL = 0x00000272L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA224 = 0x00000255L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA224_HMAC = 0x00000256L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA224_HMAC_GENERAL = 0x00000257L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SECURID_KEY_GEN = 0x00000280L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SECURID = 0x00000282L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_HOTP_KEY_GEN = 0x00000290L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_HOTP = 0x00000291L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ACTI = 0x000002A0L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ACTI_KEY_GEN = 0x000002A1L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_256 = 0x000002B0L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_256_HMAC = 0x000002B1L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_256_HMAC_GENERAL = 0x000002B2L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_256_KEY_GEN = 0x000002B3L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_224 = 0x000002B5L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_224_HMAC = 0x000002B6L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_224_HMAC_GENERAL = 0x000002B7L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_224_KEY_GEN = 0x000002B8L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_384 = 0x000002C0L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_384_HMAC = 0x000002C1L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_384_HMAC_GENERAL = 0x000002C2L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_384_KEY_GEN = 0x000002C3L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_512 = 0x000002D0L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_512_HMAC = 0x000002D1L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_512_HMAC_GENERAL = 0x000002D2L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_512_KEY_GEN = 0x000002D3L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST_KEY_GEN = 0x00000300L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST_ECB = 0x00000301L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST_CBC = 0x00000302L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST_MAC = 0x00000303L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST_MAC_GENERAL = 0x00000304L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST_CBC_PAD = 0x00000305L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST3_KEY_GEN = 0x00000310L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST3_ECB = 0x00000311L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST3_CBC = 0x00000312L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST3_MAC = 0x00000313L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST3_MAC_GENERAL = 0x00000314L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST3_CBC_PAD = 0x00000315L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST5_KEY_GEN = 0x00000320L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST128_KEY_GEN = 0x00000320L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST5_ECB = 0x00000321L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST128_ECB = 0x00000321L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST5_CBC = 0x00000322L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST128_CBC = 0x00000322L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST5_MAC = 0x00000323L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST128_MAC = 0x00000323L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST5_MAC_GENERAL = 0x00000324L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST128_MAC_GENERAL = 0x00000324L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST5_CBC_PAD = 0x00000325L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAST128_CBC_PAD = 0x00000325L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RC5_KEY_GEN = 0x00000330L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RC5_ECB = 0x00000331L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RC5_CBC = 0x00000332L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RC5_MAC = 0x00000333L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RC5_MAC_GENERAL = 0x00000334L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RC5_CBC_PAD = 0x00000335L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_IDEA_KEY_GEN = 0x00000340L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_IDEA_ECB = 0x00000341L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_IDEA_CBC = 0x00000342L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_IDEA_MAC = 0x00000343L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_IDEA_MAC_GENERAL = 0x00000344L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_IDEA_CBC_PAD = 0x00000345L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_GENERIC_SECRET_KEY_GEN = 0x00000350L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CONCATENATE_BASE_AND_KEY = 0x00000360L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CONCATENATE_BASE_AND_DATA = 0x00000362L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CONCATENATE_DATA_AND_BASE = 0x00000363L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_XOR_BASE_AND_DATA = 0x00000364L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_EXTRACT_KEY_FROM_KEY = 0x00000365L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SSL3_PRE_MASTER_KEY_GEN = 0x00000370L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SSL3_MASTER_KEY_DERIVE = 0x00000371L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SSL3_KEY_AND_MAC_DERIVE = 0x00000372L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SSL3_MASTER_KEY_DERIVE_DH = 0x00000373L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_TLS_PRE_MASTER_KEY_GEN = 0x00000374L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_TLS_MASTER_KEY_DERIVE = 0x00000375L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_TLS_KEY_AND_MAC_DERIVE = 0x00000376L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_TLS_MASTER_KEY_DERIVE_DH = 0x00000377L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_TLS_PRF = 0x00000378L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SSL3_MD5_MAC = 0x00000380L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SSL3_SHA1_MAC = 0x00000381L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_MD5_KEY_DERIVATION = 0x00000390L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_MD2_KEY_DERIVATION = 0x00000391L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA1_KEY_DERIVATION = 0x00000392L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA256_KEY_DERIVATION = 0x00000393L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA384_KEY_DERIVATION = 0x00000394L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512_KEY_DERIVATION = 0x00000395L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA224_KEY_DERIVATION = 0x00000396L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_256_KEY_DERIVATION = 0x00000397L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_224_KEY_DERIVATION = 0x00000398L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_384_KEY_DERIVATION = 0x00000399L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA3_512_KEY_DERIVATION = 0x0000039AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHAKE_128_KEY_DERIVATION = 0x0000039BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHAKE_256_KEY_DERIVATION = 0x0000039CL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_PBE_MD2_DES_CBC = 0x000003A0L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_PBE_MD5_DES_CBC = 0x000003A1L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_PBE_MD5_CAST_CBC = 0x000003A2L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_PBE_MD5_CAST3_CBC = 0x000003A3L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_PBE_MD5_CAST5_CBC = 0x000003A4L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_PBE_MD5_CAST128_CBC = 0x000003A4L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_PBE_SHA1_CAST5_CBC = 0x000003A5L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_PBE_SHA1_CAST128_CBC = 0x000003A5L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_PBE_SHA1_RC4_128 = 0x000003A6L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_PBE_SHA1_RC4_40 = 0x000003A7L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_PBE_SHA1_DES3_EDE_CBC = 0x000003A8L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_PBE_SHA1_DES2_EDE_CBC = 0x000003A9L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_PBE_SHA1_RC2_128_CBC = 0x000003AAL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_PBE_SHA1_RC2_40_CBC = 0x000003ABL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_PKCS5_PBKD2 = 0x000003B0L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_PBA_SHA1_WITH_SHA1_HMAC = 0x000003C0L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_WTLS_PRE_MASTER_KEY_GEN = 0x000003D0L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_WTLS_MASTER_KEY_DERIVE = 0x000003D1L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_WTLS_MASTER_KEY_DERIVE_DH_ECC = 0x000003D2L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_WTLS_PRF = 0x000003D3L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE = 0x000003D4L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE = 0x000003D5L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_TLS12_MASTER_KEY_DERIVE = 0x000003E0L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_TLS12_KEY_AND_MAC_DERIVE = 0x000003E1L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_TLS12_MASTER_KEY_DERIVE_DH = 0x000003E2L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_TLS12_KEY_SAFE_DERIVE = 0x000003E3L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_TLS12_MAC = 0x000003D8L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_TLS12_KDF = 0x000003D9L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_TLS_MAC = 0x000003E4L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_TLS_KDF = 0x000003E5L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_KEY_WRAP_LYNKS = 0x00000400L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_KEY_WRAP_SET_OAEP = 0x00000401L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CMS_SIG = 0x00000500L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_KIP_DERIVE = 0x00000510L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_KIP_WRAP = 0x00000511L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_KIP_MAC = 0x00000512L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SKIPJACK_KEY_GEN = 0x00001000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SKIPJACK_ECB64 = 0x00001001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SKIPJACK_CBC64 = 0x00001002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SKIPJACK_OFB64 = 0x00001003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SKIPJACK_CFB64 = 0x00001004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SKIPJACK_CFB32 = 0x00001005L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SKIPJACK_CFB16 = 0x00001006L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SKIPJACK_CFB8 = 0x00001007L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SKIPJACK_WRAP = 0x00001008L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SKIPJACK_PRIVATE_WRAP = 0x00001009L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SKIPJACK_RELAYX = 0x0000100AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_KEA_KEY_PAIR_GEN = 0x00001010L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_KEA_KEY_DERIVE = 0x00001011L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_FORTEZZA_TIMESTAMP = 0x00001020L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BATON_KEY_GEN = 0x00001030L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BATON_ECB128 = 0x00001031L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BATON_ECB96 = 0x00001032L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BATON_CBC128 = 0x00001033L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BATON_COUNTER = 0x00001034L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BATON_SHUFFLE = 0x00001035L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BATON_WRAP = 0x00001036L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ECDSA_KEY_PAIR_GEN = 0x00001040L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_EC_KEY_PAIR_GEN = 0x00001040L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ECDSA = 0x00001041L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ECDSA_SHA1 = 0x00001042L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ECDSA_SHA224 = 0x00001043L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ECDSA_SHA256 = 0x00001044L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ECDSA_SHA384 = 0x00001045L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ECDSA_SHA512 = 0x00001046L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_EC_KEY_PAIR_GEN_W_EXTRA_BITS = 0x0000140BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ECDH1_DERIVE = 0x00001050L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ECDH1_COFACTOR_DERIVE = 0x00001051L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ECMQV_DERIVE = 0x00001052L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ECDH_AES_KEY_WRAP = 0x00001053L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RSA_AES_KEY_WRAP = 0x00001054L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_JUNIPER_KEY_GEN = 0x00001060L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_JUNIPER_ECB128 = 0x00001061L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_JUNIPER_CBC128 = 0x00001062L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_JUNIPER_COUNTER = 0x00001063L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_JUNIPER_SHUFFLE = 0x00001064L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_JUNIPER_WRAP = 0x00001065L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_FASTHASH = 0x00001070L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_AES_KEY_GEN = 0x00001080L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_AES_ECB = 0x00001081L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_AES_CBC = 0x00001082L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_AES_MAC = 0x00001083L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_AES_MAC_GENERAL = 0x00001084L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_AES_CBC_PAD = 0x00001085L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_AES_CTR = 0x00001086L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_AES_GCM = 0x00001087L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_AES_CCM = 0x00001088L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_AES_CTS = 0x00001089L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_AES_CMAC = 0x0000108AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_AES_CMAC_GENERAL = 0x0000108BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_AES_XCBC_MAC = 0x0000108CL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_AES_XCBC_MAC_96 = 0x0000108DL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLOWFISH_KEY_GEN = 0x00001090L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLOWFISH_CBC = 0x00001091L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_TWOFISH_KEY_GEN = 0x00001092L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_TWOFISH_CBC = 0x00001093L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLOWFISH_CBC_PAD = 0x00001094L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_TWOFISH_CBC_PAD = 0x00001095L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAMELLIA_KEY_GEN = 0x00000550L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAMELLIA_ECB = 0x00000551L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAMELLIA_CBC = 0x00000552L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAMELLIA_MAC = 0x00000553L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAMELLIA_MAC_GENERAL = 0x00000554L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAMELLIA_CBC_PAD = 0x00000555L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAMELLIA_ECB_ENCRYPT_DATA = 0x00000556L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CAMELLIA_CBC_ENCRYPT_DATA = 0x00000557L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ARIA_KEY_GEN = 0x00000560L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ARIA_ECB = 0x00000561L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ARIA_CBC = 0x00000562L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ARIA_MAC = 0x00000563L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ARIA_MAC_GENERAL = 0x00000564L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ARIA_CBC_PAD = 0x00000565L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ARIA_ECB_ENCRYPT_DATA = 0x00000566L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ARIA_CBC_ENCRYPT_DATA = 0x00000567L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SEED_KEY_GEN = 0x00000650L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SEED_ECB = 0x00000651L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SEED_CBC = 0x00000652L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SEED_MAC = 0x00000653L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SEED_MAC_GENERAL = 0x00000654L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SEED_CBC_PAD = 0x00000655L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SEED_ECB_ENCRYPT_DATA = 0x00000656L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SEED_CBC_ENCRYPT_DATA = 0x00000657L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ECDSA_SHA3_224 = 0x00001047L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ECDSA_SHA3_256 = 0x00001048L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ECDSA_SHA3_384 = 0x00001049L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_ECDSA_SHA3_512 = 0x0000104AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_EC_EDWARDS_KEY_PAIR_GEN = 0x00001055L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_EC_MONTGOMERY_KEY_PAIR_GEN = 0x00001056L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_EDDSA = 0x00001057L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DES_ECB_ENCRYPT_DATA = 0x00001100L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DES_CBC_ENCRYPT_DATA = 0x00001101L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DES3_ECB_ENCRYPT_DATA = 0x00001102L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DES3_CBC_ENCRYPT_DATA = 0x00001103L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_AES_ECB_ENCRYPT_DATA = 0x00001104L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_AES_CBC_ENCRYPT_DATA = 0x00001105L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_GOSTR3410_KEY_PAIR_GEN = 0x00001200L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_GOSTR3410 = 0x00001201L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_GOSTR3410_WITH_GOSTR3411 = 0x00001202L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_GOSTR3410_KEY_WRAP = 0x00001203L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_GOSTR3410_DERIVE = 0x00001204L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_GOSTR3411 = 0x00001210L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_GOSTR3411_HMAC = 0x00001211L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_GOST28147_KEY_GEN = 0x00001220L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_GOST28147_ECB = 0x00001221L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_GOST28147 = 0x00001222L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_GOST28147_MAC = 0x00001223L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_GOST28147_KEY_WRAP = 0x00001224L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CHACHA20_KEY_GEN = 0x00001225L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CHACHA20 = 0x00001226L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_POLY1305_KEY_GEN = 0x00001227L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_POLY1305 = 0x00001228L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DSA_PARAMETER_GEN = 0x00002000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DH_PKCS_PARAMETER_GEN = 0x00002001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_X9_42_DH_PARAMETER_GEN = 0x00002002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DSA_PROBABILISTIC_PARAMETER_GEN = 0x00002003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DSA_SHAWE_TAYLOR_PARAMETER_GEN = 0x00002004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_DSA_FIPS_G_GEN = 0x00002005L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_AES_CFB1 = 0x00002108L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_AES_KEY_WRAP = 0x00002109L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_AES_KEY_WRAP_PAD = 0x0000210AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_AES_KEY_WRAP_KWP = 0x0000210BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SP800_108_COUNTER_KDF = 0x000003ACL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SP800_108_FEEDBACK_KDF = 0x000003ADL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SP800_108_DOUBLE_PIPELINE_KDF = 0x000003AEL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RSA_PKCS_TPM_1_1 = 0x00004001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_RSA_PKCS_OAEP_TPM_1_1 = 0x00004002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA_1_KEY_GEN = 0x00004003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA224_KEY_GEN = 0x00004004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA256_KEY_GEN = 0x00004005L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA384_KEY_GEN = 0x00004006L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512_KEY_GEN = 0x00004007L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512_224_KEY_GEN = 0x00004008L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512_256_KEY_GEN = 0x00004009L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SHA512_T_KEY_GEN = 0x0000400AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_NULL = 0x0000400BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLAKE2B_160 = 0x0000400CL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLAKE2B_160_HMAC = 0x0000400DL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLAKE2B_160_HMAC_GENERAL = 0x0000400EL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLAKE2B_160_KEY_DERIVE = 0x0000400FL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLAKE2B_160_KEY_GEN = 0x00004010L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLAKE2B_256 = 0x00004011L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLAKE2B_256_HMAC = 0x00004012L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLAKE2B_256_HMAC_GENERAL = 0x00004013L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLAKE2B_256_KEY_DERIVE = 0x00004014L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLAKE2B_256_KEY_GEN = 0x00004015L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLAKE2B_384 = 0x00004016L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLAKE2B_384_HMAC = 0x00004017L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLAKE2B_384_HMAC_GENERAL = 0x00004018L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLAKE2B_384_KEY_DERIVE = 0x00004019L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLAKE2B_384_KEY_GEN = 0x0000401AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLAKE2B_512 = 0x0000401BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLAKE2B_512_HMAC = 0x0000401CL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLAKE2B_512_HMAC_GENERAL = 0x0000401DL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLAKE2B_512_KEY_DERIVE = 0x0000401EL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_BLAKE2B_512_KEY_GEN = 0x0000401FL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SALSA20 = 0x00004020L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_CHACHA20_POLY1305 = 0x00004021L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SALSA20_POLY1305 = 0x00004022L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_X3DH_INITIALIZE = 0x00004023L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_X3DH_RESPOND = 0x00004024L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_X2RATCHET_INITIALIZE = 0x00004025L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_X2RATCHET_RESPOND = 0x00004026L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_X2RATCHET_ENCRYPT = 0x00004027L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_X2RATCHET_DECRYPT = 0x00004028L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_XEDDSA = 0x00004029L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_HKDF_DERIVE = 0x0000402AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_HKDF_DATA = 0x0000402BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_HKDF_KEY_GEN = 0x0000402CL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_SALSA20_KEY_GEN = 0x0000402DL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKM_VENDOR_DEFINED = 0x80000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_HW = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_MESSAGE_ENCRYPT = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_MESSAGE_DECRYPT = 0x00000004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_MESSAGE_SIGN = 0x00000008L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_MESSAGE_VERIFY = 0x00000010L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_MULTI_MESSAGE = 0x00000020L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_FIND_OBJECTS = 0x00000040L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_ENCRYPT = 0x00000100L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_DECRYPT = 0x00000200L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_DIGEST = 0x00000400L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_SIGN = 0x00000800L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_SIGN_RECOVER = 0x00001000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_VERIFY = 0x00002000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_VERIFY_RECOVER = 0x00004000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_GENERATE = 0x00008000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_GENERATE_KEY_PAIR = 0x00010000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_WRAP = 0x00020000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_UNWRAP = 0x00040000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_DERIVE = 0x00080000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_EC_F_P = 0x00100000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_EC_F_2M = 0x00200000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_EC_ECPARAMETERS = 0x00400000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_EC_OID = 0x00800000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_EC_NAMEDCURVE = 0x00800000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_EC_UNCOMPRESS = 0x01000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_EC_COMPRESS = 0x02000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_EXTENSION = 0x80000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_OK = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_CANCEL = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_HOST_MEMORY = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_SLOT_ID_INVALID = 0x00000003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_GENERAL_ERROR = 0x00000005L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_FUNCTION_FAILED = 0x00000006L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_ARGUMENTS_BAD = 0x00000007L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_NO_EVENT = 0x00000008L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_NEED_TO_CREATE_THREADS = 0x00000009L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_CANT_LOCK = 0x0000000AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_ATTRIBUTE_READ_ONLY = 0x00000010L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_ATTRIBUTE_SENSITIVE = 0x00000011L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_ATTRIBUTE_TYPE_INVALID = 0x00000012L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_ATTRIBUTE_VALUE_INVALID = 0x00000013L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_ACTION_PROHIBITED = 0x0000001BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_DATA_INVALID = 0x00000020L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_DATA_LEN_RANGE = 0x00000021L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_DEVICE_ERROR = 0x00000030L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_DEVICE_MEMORY = 0x00000031L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_DEVICE_REMOVED = 0x00000032L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_ENCRYPTED_DATA_INVALID = 0x00000040L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_ENCRYPTED_DATA_LEN_RANGE = 0x00000041L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_FUNCTION_CANCELED = 0x00000050L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_FUNCTION_NOT_PARALLEL = 0x00000051L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_FUNCTION_NOT_SUPPORTED = 0x00000054L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_KEY_HANDLE_INVALID = 0x00000060L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_KEY_SIZE_RANGE = 0x00000062L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_KEY_TYPE_INCONSISTENT = 0x00000063L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_KEY_NOT_NEEDED = 0x00000064L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_KEY_CHANGED = 0x00000065L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_KEY_NEEDED = 0x00000066L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_KEY_INDIGESTIBLE = 0x00000067L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_KEY_FUNCTION_NOT_PERMITTED = 0x00000068L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_KEY_NOT_WRAPPABLE = 0x00000069L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_KEY_UNEXTRACTABLE = 0x0000006AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_MECHANISM_INVALID = 0x00000070L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_MECHANISM_PARAM_INVALID = 0x00000071L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_OBJECT_HANDLE_INVALID = 0x00000082L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_OPERATION_ACTIVE = 0x00000090L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_OPERATION_NOT_INITIALIZED = 0x00000091L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_PIN_INCORRECT = 0x000000A0L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_PIN_INVALID = 0x000000A1L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_PIN_LEN_RANGE = 0x000000A2L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_PIN_EXPIRED = 0x000000A3L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_PIN_LOCKED = 0x000000A4L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_SESSION_CLOSED = 0x000000B0L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_SESSION_COUNT = 0x000000B1L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_SESSION_HANDLE_INVALID = 0x000000B3L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_SESSION_PARALLEL_NOT_SUPPORTED = 0x000000B4L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_SESSION_READ_ONLY = 0x000000B5L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_SESSION_EXISTS = 0x000000B6L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_SESSION_READ_ONLY_EXISTS = 0x000000B7L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_SESSION_READ_WRITE_SO_EXISTS = 0x000000B8L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_SIGNATURE_INVALID = 0x000000C0L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_SIGNATURE_LEN_RANGE = 0x000000C1L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_TEMPLATE_INCOMPLETE = 0x000000D0L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_TEMPLATE_INCONSISTENT = 0x000000D1L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_TOKEN_NOT_PRESENT = 0x000000E0L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_TOKEN_NOT_RECOGNIZED = 0x000000E1L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_TOKEN_WRITE_PROTECTED = 0x000000E2L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_UNWRAPPING_KEY_HANDLE_INVALID = 0x000000F0L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_UNWRAPPING_KEY_SIZE_RANGE = 0x000000F1L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT = 0x000000F2L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_USER_ALREADY_LOGGED_IN = 0x00000100L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_USER_NOT_LOGGED_IN = 0x00000101L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_USER_PIN_NOT_INITIALIZED = 0x00000102L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_USER_TYPE_INVALID = 0x00000103L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_USER_ANOTHER_ALREADY_LOGGED_IN = 0x00000104L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_USER_TOO_MANY_TYPES = 0x00000105L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_WRAPPED_KEY_INVALID = 0x00000110L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_WRAPPED_KEY_LEN_RANGE = 0x00000112L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_WRAPPING_KEY_HANDLE_INVALID = 0x00000113L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_WRAPPING_KEY_SIZE_RANGE = 0x00000114L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_WRAPPING_KEY_TYPE_INCONSISTENT = 0x00000115L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_RANDOM_SEED_NOT_SUPPORTED = 0x00000120L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_RANDOM_NO_RNG = 0x00000121L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_DOMAIN_PARAMS_INVALID = 0x00000130L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_CURVE_NOT_SUPPORTED = 0x00000140L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_BUFFER_TOO_SMALL = 0x00000150L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_SAVED_STATE_INVALID = 0x00000160L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_INFORMATION_SENSITIVE = 0x00000170L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_STATE_UNSAVEABLE = 0x00000180L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_CRYPTOKI_NOT_INITIALIZED = 0x00000190L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_CRYPTOKI_ALREADY_INITIALIZED = 0x00000191L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_MUTEX_BAD = 0x000001A0L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_MUTEX_NOT_LOCKED = 0x000001A1L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_NEW_PIN_MODE = 0x000001B0L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_NEXT_OTP = 0x000001B1L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_EXCEEDED_MAX_ITERATIONS = 0x000001B5L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_FIPS_SELF_TEST_FAILED = 0x000001B6L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_LIBRARY_LOAD_FAILED = 0x000001B7L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_PIN_TOO_WEAK = 0x000001B8L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_PUBLIC_KEY_INVALID = 0x000001B9L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_FUNCTION_REJECTED = 0x00000200L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_TOKEN_RESOURCE_EXCEEDED = 0x00000201L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_OPERATION_CANCEL_FAILED = 0x00000202L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKR_VENDOR_DEFINED = 0x80000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_END_OF_MESSAGE = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_INTERFACE_FORK_SAFE = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_LIBRARY_CANT_CREATE_OS_THREADS = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_OS_LOCKING_OK = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_DONT_BLOCK = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKG_MGF1_SHA1 = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKG_MGF1_SHA256 = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKG_MGF1_SHA384 = 0x00000003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKG_MGF1_SHA512 = 0x00000004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKG_MGF1_SHA224 = 0x00000005L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKG_MGF1_SHA3_224 = 0x00000006L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKG_MGF1_SHA3_256 = 0x00000007L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKG_MGF1_SHA3_384 = 0x00000008L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKG_MGF1_SHA3_512 = 0x00000009L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKZ_DATA_SPECIFIED = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_NULL = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_SHA1_KDF = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_SHA224_KDF = 0x00000005L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_SHA256_KDF = 0x00000006L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_SHA384_KDF = 0x00000007L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_SHA512_KDF = 0x00000008L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_CPDIVERSIFY_KDF = 0x00000009L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_SHA3_224_KDF = 0x0000000AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_SHA3_256_KDF = 0x0000000BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_SHA3_384_KDF = 0x0000000CL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_SHA3_512_KDF = 0x0000000DL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_SHA1_KDF_SP800 = 0x0000000EL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_SHA224_KDF_SP800 = 0x0000000FL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_SHA256_KDF_SP800 = 0x00000010L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_SHA384_KDF_SP800 = 0x00000011L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_SHA512_KDF_SP800 = 0x00000012L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_SHA3_224_KDF_SP800 = 0x00000013L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_SHA3_256_KDF_SP800 = 0x00000014L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_SHA3_384_KDF_SP800 = 0x00000015L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_SHA3_512_KDF_SP800 = 0x00000016L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_BLAKE2B_160_KDF = 0x00000017L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_BLAKE2B_256_KDF = 0x00000018L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_BLAKE2B_384_KDF = 0x00000019L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_BLAKE2B_512_KDF = 0x0000001AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_SHA1_KDF_ASN1 = 0x00000003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKD_SHA1_KDF_CONCATENATE = 0x00000004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKG_NO_GENERATE = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKG_GENERATE = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKG_GENERATE_COUNTER = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKG_GENERATE_RANDOM = 0x00000003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKG_GENERATE_COUNTER_XOR = 0x00000004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_HKDF_SALT_NULL = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_HKDF_SALT_DATA = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_HKDF_SALT_KEY = 0x00000004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_SP800_108_ITERATION_VARIABLE = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_SP800_108_OPTIONAL_COUNTER = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_SP800_108_DKM_LENGTH = 0x00000003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_SP800_108_BYTE_ARRAY = 0x00000004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_SP800_108_COUNTER = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_SP800_108_DKM_LENGTH_SUM_OF_KEYS = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_SP800_108_DKM_LENGTH_SUM_OF_SEGMENTS = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKP_PKCS5_PBKD2_HMAC_SHA1 = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKP_PKCS5_PBKD2_HMAC_GOSTR3411 = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKP_PKCS5_PBKD2_HMAC_SHA224 = 0x00000003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKP_PKCS5_PBKD2_HMAC_SHA256 = 0x00000004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKP_PKCS5_PBKD2_HMAC_SHA384 = 0x00000005L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKP_PKCS5_PBKD2_HMAC_SHA512 = 0x00000006L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKP_PKCS5_PBKD2_HMAC_SHA512_224 = 0x00000007L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKP_PKCS5_PBKD2_HMAC_SHA512_256 = 0x00000008L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKZ_SALT_SPECIFIED = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_OTP_VALUE = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_OTP_PIN = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_OTP_CHALLENGE = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_OTP_TIME = 0x00000003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_OTP_COUNTER = 0x00000004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_OTP_FLAGS = 0x00000005L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_OTP_OUTPUT_LENGTH = 0x00000006L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CK_OTP_OUTPUT_FORMAT = 0x00000007L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_NEXT_OTP = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_EXCLUDE_TIME = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_EXCLUDE_COUNTER = 0x00000004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_EXCLUDE_CHALLENGE = 0x00000008L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_EXCLUDE_PIN = 0x00000010L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKF_USER_FRIENDLY_OTP = 0x00000020L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11t.h */ public static final long CKK_INVALID_KEY_TYPE = 0xFFFFFFFFL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long NSSCK_VENDOR_NSS = 0x4E534350L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKO_NSS = 0xCE534350L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKO_NSS_CRL = 0xCE534351L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKO_NSS_SMIME = 0xCE534352L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKO_NSS_TRUST = 0xCE534353L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKO_NSS_BUILTIN_ROOT_LIST = 0xCE534354L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKO_NSS_NEWSLOT = 0xCE534355L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKO_NSS_DELSLOT = 0xCE534356L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKK_NSS = 0xCE534350L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKK_NSS_PKCS8 = 0xCE534351L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKK_NSS_JPAKE_ROUND1 = 0xCE534352L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKK_NSS_JPAKE_ROUND2 = 0xCE534353L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKK_NSS_CHACHA20 = 0xCE534354L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKC_NSS = 0xCE534350L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_DIGEST = 0x81000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_MESSAGE = 0x82000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_MESSAGE_MASK = 0xFF000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_FLAGS_ONLY = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS = 0xCE534350L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_URL = 0xCE534351L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_EMAIL = 0xCE534352L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_SMIME_INFO = 0xCE534353L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_SMIME_TIMESTAMP = 0xCE534354L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_PKCS8_SALT = 0xCE534355L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_PASSWORD_CHECK = 0xCE534356L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_EXPIRES = 0xCE534357L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_KRL = 0xCE534358L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_PQG_COUNTER = 0xCE534364L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_PQG_SEED = 0xCE534365L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_PQG_H = 0xCE534366L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_PQG_SEED_BITS = 0xCE534367L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_MODULE_SPEC = 0xCE534368L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_OVERRIDE_EXTENSIONS = 0xCE534369L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_JPAKE_SIGNERID = 0xCE53436AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_JPAKE_PEERID = 0xCE53436BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_JPAKE_GX1 = 0xCE53436CL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_JPAKE_GX2 = 0xCE53436DL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_JPAKE_GX3 = 0xCE53436EL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_JPAKE_GX4 = 0xCE53436FL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_JPAKE_X2 = 0xCE534370L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_JPAKE_X2S = 0xCE534371L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_MOZILLA_CA_POLICY = 0xCE534372L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_SERVER_DISTRUST_AFTER = 0xCE534373L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_EMAIL_DISTRUST_AFTER = 0xCE534374L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_TRUST = 0xCE536350L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_TRUST_DIGITAL_SIGNATURE = 0xCE536351L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_TRUST_NON_REPUDIATION = 0xCE536352L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_TRUST_KEY_ENCIPHERMENT = 0xCE536353L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_TRUST_DATA_ENCIPHERMENT = 0xCE536354L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_TRUST_KEY_AGREEMENT = 0xCE536355L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_TRUST_KEY_CERT_SIGN = 0xCE536356L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_TRUST_CRL_SIGN = 0xCE536357L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_TRUST_SERVER_AUTH = 0xCE536358L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_TRUST_CLIENT_AUTH = 0xCE536359L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_TRUST_CODE_SIGNING = 0xCE53635AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_TRUST_EMAIL_PROTECTION = 0xCE53635BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_TRUST_IPSEC_END_SYSTEM = 0xCE53635CL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_TRUST_IPSEC_TUNNEL = 0xCE53635DL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_TRUST_IPSEC_USER = 0xCE53635EL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_TRUST_TIME_STAMPING = 0xCE53635FL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_TRUST_STEP_UP_APPROVED = 0xCE536360L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_CERT_SHA1_HASH = 0xCE5363B4L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_CERT_MD5_HASH = 0xCE5363B5L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_DB = 0xD5A0DB00L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NSS_TRUST = 0x80000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_FAKE_RANDOM = 0x80000EFEL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_INVALID_MECHANISM = 0xFFFFFFFFL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_INVALID_TYPE = 0xFFFFFFFFL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS = 0xCE534350L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_AES_KEY_WRAP = 0xCE534351L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_AES_KEY_WRAP_PAD = 0xCE534352L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_HKDF_SHA1 = 0xCE534353L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_HKDF_SHA256 = 0xCE534354L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_HKDF_SHA384 = 0xCE534355L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_HKDF_SHA512 = 0xCE534356L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_JPAKE_ROUND1_SHA1 = 0xCE534357L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_JPAKE_ROUND1_SHA256 = 0xCE534358L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_JPAKE_ROUND1_SHA384 = 0xCE534359L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_JPAKE_ROUND1_SHA512 = 0xCE53435AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_JPAKE_ROUND2_SHA1 = 0xCE53435BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_JPAKE_ROUND2_SHA256 = 0xCE53435CL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_JPAKE_ROUND2_SHA384 = 0xCE53435DL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_JPAKE_ROUND2_SHA512 = 0xCE53435EL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_JPAKE_FINAL_SHA1 = 0xCE53435FL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_JPAKE_FINAL_SHA256 = 0xCE534360L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_JPAKE_FINAL_SHA384 = 0xCE534361L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_JPAKE_FINAL_SHA512 = 0xCE534362L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_HMAC_CONSTANT_TIME = 0xCE534363L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_SSL3_MAC_CONSTANT_TIME = 0xCE534364L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_TLS_PRF_GENERAL_SHA256 = 0xCE534365L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_TLS_MASTER_KEY_DERIVE_SHA256 = 0xCE534366L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_TLS_KEY_AND_MAC_DERIVE_SHA256 = 0xCE534367L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256 = 0xCE534368L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE = 0xCE534369L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_TLS_EXTENDED_MASTER_KEY_DERIVE_DH = 0xCE53436AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_CHACHA20_KEY_GEN = 0xCE53436BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_CHACHA20_POLY1305 = 0xCE53436CL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_PKCS12_PBE_SHA224_HMAC_KEY_GEN = 0xCE53436DL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_PKCS12_PBE_SHA256_HMAC_KEY_GEN = 0xCE53436EL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_PKCS12_PBE_SHA384_HMAC_KEY_GEN = 0xCE53436FL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_PKCS12_PBE_SHA512_HMAC_KEY_GEN = 0xCE534370L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_CHACHA20_CTR = 0xCE534371L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_IKE_PRF_PLUS_DERIVE = 0xCE534372L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_IKE_PRF_DERIVE = 0xCE534373L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_IKE1_PRF_DERIVE = 0xCE534374L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_IKE1_APP_B_PRF_DERIVE = 0xCE534375L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_PUB_FROM_PRIV = 0xCE534378L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA = 0xCE53437AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA = 0xCE53437BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA = 0xCE53437CL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_PBE_SHA1_DES_CBC = 0x80000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_PBE_SHA1_TRIPLE_DES_CBC = 0x80000003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_PBE_SHA1_40_BIT_RC2_CBC = 0x80000004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_PBE_SHA1_128_BIT_RC2_CBC = 0x80000005L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_PBE_SHA1_40_BIT_RC4 = 0x80000006L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_PBE_SHA1_128_BIT_RC4 = 0x80000007L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_PBE_SHA1_FAULTY_3DES_CBC = 0x80000008L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_PBE_SHA1_HMAC_KEY_GEN = 0x80000009L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_PBE_MD5_HMAC_KEY_GEN = 0x8000000AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NSS_PBE_MD2_HMAC_KEY_GEN = 0x8000000BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_TLS_PRF_GENERAL = 0x80000373L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKS_NSS_UNINITIALIZED = 0xFFFFFFFFL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKS_NSS_FIPS_NOT_OK = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKS_NSS_FIPS_OK = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_NSS_SESSION_CHECK = 0x00000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_NSS_OBJECT_CHECK = 0x00000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_NSS_BOTH_CHECK = 0x00000003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_NSS_SESSION_LAST_CHECK = 0x00000004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKR_NSS = 0xCE534350L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKR_NSS_CERTDB_FAILED = 0xCE534351L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKR_NSS_KEYDB_FAILED = 0xCE534352L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_VENDOR_DEFINED = 0x80000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_NSS = 0xCE534350L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_NSS_TRUSTED = 0xCE534351L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_NSS_TRUSTED_DELEGATOR = 0xCE534352L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_NSS_MUST_VERIFY_TRUST = 0xCE534353L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_NSS_NOT_TRUSTED = 0xCE53435AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_NSS_TRUST_UNKNOWN = 0xCE534355L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_NSS_VALID_DELEGATOR = 0xCE53435BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_NSS_UNTRUSTED = 0xCE534353L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_NSS_VALID = 0xCE53435AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_NSS_MUST_VERIFY = 0xCE534354L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long SFTK_MIN_USER_SLOT_ID = 0x00000004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long SFTK_MAX_USER_SLOT_ID = 0x00000064L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long SFTK_MIN_FIPS_USER_SLOT_ID = 0x00000065L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long SFTK_MAX_FIPS_USER_SLOT_ID = 0x0000007FL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKF_EC_FP = 0x00100000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKO_KG_PARAMETERS = 0x00000006L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CK_INVALID_SESSION = 0x00000000L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKR_KEY_PARAMS_INVALID = 0x0000006BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKO_NETSCAPE_CRL = 0xCE534351L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKO_NETSCAPE_SMIME = 0xCE534352L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKO_NETSCAPE_TRUST = 0xCE534353L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKO_NETSCAPE_BUILTIN_ROOT_LIST = 0xCE534354L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKO_NETSCAPE_NEWSLOT = 0xCE534355L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKO_NETSCAPE_DELSLOT = 0xCE534356L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKK_NETSCAPE_PKCS8 = 0xCE534351L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NETSCAPE_URL = 0xCE534351L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NETSCAPE_EMAIL = 0xCE534352L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NETSCAPE_SMIME_INFO = 0xCE534353L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NETSCAPE_SMIME_TIMESTAMP = 0xCE534354L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NETSCAPE_PKCS8_SALT = 0xCE534355L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NETSCAPE_PASSWORD_CHECK = 0xCE534356L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NETSCAPE_EXPIRES = 0xCE534357L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NETSCAPE_KRL = 0xCE534358L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NETSCAPE_PQG_COUNTER = 0xCE534364L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NETSCAPE_PQG_SEED = 0xCE534365L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NETSCAPE_PQG_H = 0xCE534366L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NETSCAPE_PQG_SEED_BITS = 0xCE534367L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NETSCAPE_MODULE_SPEC = 0xCE534368L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NETSCAPE_DB = 0xD5A0DB00L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKA_NETSCAPE_TRUST = 0x80000001L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NETSCAPE_AES_KEY_WRAP = 0xCE534351L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NETSCAPE_AES_KEY_WRAP_PAD = 0xCE534352L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NETSCAPE_PBE_SHA1_DES_CBC = 0x80000002L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC = 0x80000003L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC = 0x80000004L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC = 0x80000005L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4 = 0x80000006L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4 = 0x80000007L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC = 0x80000008L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN = 0x80000009L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN = 0x8000000AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN = 0x8000000BL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKR_NETSCAPE_CERTDB_FAILED = 0xCE534351L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKR_NETSCAPE_KEYDB_FAILED = 0xCE534352L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_NETSCAPE_TRUSTED = 0xCE534351L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_NETSCAPE_TRUSTED_DELEGATOR = 0xCE534352L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_NETSCAPE_UNTRUSTED = 0xCE534353L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_NETSCAPE_MUST_VERIFY = 0xCE534354L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_NETSCAPE_TRUST_UNKNOWN = 0xCE534355L; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_NETSCAPE_VALID = 0xCE53435AL; /** * Content automatically generated; see NSS documentation for more information. * * Source file: /usr/include/nss3/pkcs11n.h */ public static final long CKT_NETSCAPE_VALID_DELEGATOR = 0xCE53435BL; } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/TokenProxy.java000066400000000000000000000011401412550063600240710ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import org.mozilla.jss.util.NativeProxy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public final class TokenProxy extends NativeProxy { public static Logger logger = LoggerFactory.getLogger(TokenProxy.class); public TokenProxy(byte[] pointer) { super(pointer); } @Override protected native void releaseNativeResources(); } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/Tunnel.java000066400000000000000000000022321412550063600232170ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs11; import org.mozilla.jss.crypto.SignatureAlgorithm; import org.mozilla.jss.crypto.SignatureSpi; import org.mozilla.jss.crypto.Signature; import org.mozilla.jss.util.Password; final class Tunnel { private static class CryptoTunnel extends org.mozilla.jss.crypto.Tunnel { public static Signature constructSignature(SignatureAlgorithm alg, SignatureSpi engine) { return ConstructSignature(alg, engine); } } private static class UtilTunnel extends org.mozilla.jss.util.Tunnel { public static byte[] getPasswordByteCopy(Password pw) { return GetPasswordByteCopy(pw); } } static Signature constructSignature(SignatureAlgorithm alg, SignatureSpi engine) { return CryptoTunnel.constructSignature(alg, engine); } static byte[] getPasswordByteCopy(Password pw) { return UtilTunnel.getPasswordByteCopy(pw); } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/attrs/000077500000000000000000000000001412550063600222455ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/attrs/CKAClass.java000066400000000000000000000060771412550063600245060ustar00rootroot00000000000000package org.mozilla.jss.pkcs11.attrs; import org.mozilla.jss.pkcs11.PKCS11Constants; /** * CKAClass is an instance of a PKCS#11 CK_ATTRIBUTE with type = CKA_CLASS. */ public class CKAClass extends CKAttribute { private long value; /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_CLASS and a * custom value. * * Note: it is generally recommended to use the subclasses of this class * instead of providing a custom value. */ public CKAClass(long value) { super(PKCS11Constants.CKA_CLASS); setValue(value); } /** * Set the value of this CKA_CLASS attribute. */ public void setValue(long value) { this.value = value; } /** * Get the value of this CKA_CLASS attribute. */ public long getValue() { return value; } @Override protected native void acquireNativeResources(); @Override protected native void releaseNativeResources(); /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_CLASS and value * CKO_DATA. */ public static class Data extends CKAClass { public Data() { super(PKCS11Constants.CKO_DATA); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_CLASS and value * CKO_CERTIFICATE. */ public static class Certificate extends CKAClass { public Certificate() { super(PKCS11Constants.CKO_CERTIFICATE); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_CLASS and value * CKO_PUBLIC_KEY. */ public static class PublicKey extends CKAClass { public PublicKey() { super(PKCS11Constants.CKO_PUBLIC_KEY); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_CLASS and value * CKO_PRIVATE_KEY. */ public static class PrivateKey extends CKAClass { public PrivateKey() { super(PKCS11Constants.CKO_PRIVATE_KEY); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_CLASS and value * CKO_SECRET_KEY. */ public static class SecretKey extends CKAClass { public SecretKey() { super(PKCS11Constants.CKO_SECRET_KEY); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_CLASS and value * CKO_HW_FEATURE. */ public static class HWFeature extends CKAClass { public HWFeature() { super(PKCS11Constants.CKO_HW_FEATURE); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_CLASS and value * CKO_DOMAIN_PARAMETERS. */ public static class DomainParameters extends CKAClass { public DomainParameters() { super(PKCS11Constants.CKO_DOMAIN_PARAMETERS); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_CLASS and value * CKO_MECHANISM. */ public static class Mechanism extends CKAClass { public Mechanism() { super(PKCS11Constants.CKO_MECHANISM); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/attrs/CKAKeyType.java000066400000000000000000000176651412550063600250400ustar00rootroot00000000000000package org.mozilla.jss.pkcs11.attrs; import org.mozilla.jss.pkcs11.PKCS11Constants; /** * CKA_KEY_TYPE is an instance of a PKCS#11 CK_ATTRIBUTE with * type = CKA_KEY_TYPE. */ public class CKAKeyType extends CKAttribute { private long value; /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and a * custom value. * * Note: it is generally recommended to use the subclasses of this class * instead of providing a custom value. */ public CKAKeyType(long value) { super(PKCS11Constants.CKA_KEY_TYPE); setValue(value); } /** * Set the value of this CKA_KEY_TYPE attribute. */ public void setValue(long value) { this.value = value; } /** * Get the value of this CKA_KEY_TYPE attribute. */ public long getValue() { return value; } @Override protected native void acquireNativeResources(); @Override protected native void releaseNativeResources(); /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_RSA. */ public static class RSA extends CKAKeyType { public RSA() { super(PKCS11Constants.CKK_RSA); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_DSA. */ public static class DSA extends CKAKeyType { public DSA() { super(PKCS11Constants.CKK_DSA); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_DH. */ public static class DH extends CKAKeyType { public DH() { super(PKCS11Constants.CKK_DH); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_ECDSA. */ public static class ECDSA extends CKAKeyType { public ECDSA() { super(PKCS11Constants.CKK_ECDSA); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_EC. */ public static class EC extends CKAKeyType { public EC() { super(PKCS11Constants.CKK_EC); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_X9_42_DH. */ public static class X9_42_DH extends CKAKeyType { public X9_42_DH() { super(PKCS11Constants.CKK_X9_42_DH); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_KEA. */ public static class KEA extends CKAKeyType { public KEA() { super(PKCS11Constants.CKK_KEA); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_GENERIC_SECRET. */ public static class GenericSecret extends CKAKeyType { public GenericSecret() { super(PKCS11Constants.CKK_GENERIC_SECRET); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_RC2. */ public static class RC2 extends CKAKeyType { public RC2() { super(PKCS11Constants.CKK_RC2); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_RC4. */ public static class RC4 extends CKAKeyType { public RC4() { super(PKCS11Constants.CKK_RC4); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_DES. */ public static class DES extends CKAKeyType { public DES() { super(PKCS11Constants.CKK_DES); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_DES2. */ public static class DES2 extends CKAKeyType { public DES2() { super(PKCS11Constants.CKK_DES2); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_DES3. */ public static class DES3 extends CKAKeyType { public DES3() { super(PKCS11Constants.CKK_DES3); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_CAST. */ public static class CAST extends CKAKeyType { public CAST() { super(PKCS11Constants.CKK_CAST); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_CAST3. */ public static class CAST3 extends CKAKeyType { public CAST3() { super(PKCS11Constants.CKK_CAST3); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_CAST5. */ public static class CAST5 extends CKAKeyType { public CAST5() { super(PKCS11Constants.CKK_CAST5); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_CAST128. */ public static class CAST128 extends CKAKeyType { public CAST128() { super(PKCS11Constants.CKK_CAST128); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_RC5. */ public static class RC5 extends CKAKeyType { public RC5() { super(PKCS11Constants.CKK_RC5); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_IDEA. */ public static class IDEA extends CKAKeyType { public IDEA() { super(PKCS11Constants.CKK_IDEA); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_SKIPJACK. */ public static class Skipjack extends CKAKeyType { public Skipjack() { super(PKCS11Constants.CKK_SKIPJACK); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_BATON. */ public static class BATON extends CKAKeyType { public BATON() { super(PKCS11Constants.CKK_BATON); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_JUNIPER. */ public static class JUNIPER extends CKAKeyType { public JUNIPER() { super(PKCS11Constants.CKK_JUNIPER); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_CDMF. */ public static class CDMF extends CKAKeyType { public CDMF() { super(PKCS11Constants.CKK_CDMF); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_AES. */ public static class AES extends CKAKeyType { public AES() { super(PKCS11Constants.CKK_AES); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_BLOWFISH. */ public static class Blowfish extends CKAKeyType { public Blowfish() { super(PKCS11Constants.CKK_BLOWFISH); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_TWOFISH. */ public static class Twofish extends CKAKeyType { public Twofish() { super(PKCS11Constants.CKK_TWOFISH); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_CAMELLIA. */ public static class Camellia extends CKAKeyType { public Camellia() { super(PKCS11Constants.CKK_CAMELLIA); } } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_KEY_TYPE and * value CKK_SEED. */ public static class Seed extends CKAKeyType { public Seed() { super(PKCS11Constants.CKK_SEED); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/attrs/CKAUsage.java000066400000000000000000000060031412550063600244720ustar00rootroot00000000000000package org.mozilla.jss.pkcs11.attrs; import org.mozilla.jss.pkcs11.PKCS11Constants; /** * CKAUsage is a collection of PKCS#11 CK_ATTRIBUTES which have common value * (CK_TRUE). */ public class CKAUsage extends CKAttribute { /** * Representation of a PKCS#11 CK_ATTRIBUTE with custom type, setting the * value to CK_TRUE. * * Note: it is generally recommended to use the subclasses of this class * instead of providing a custom value. */ public CKAUsage(long type) { super(type); } @Override protected native void acquireNativeResources(); @Override protected native void releaseNativeResources(); /** * CKAEncrypt is an instance of PKCS#11 CK_ATTRIBUTE with * type = CKA_ENCRYPT and value CK_TRUE. */ public static class Encrypt extends CKAUsage { public Encrypt() { super(PKCS11Constants.CKA_ENCRYPT); } } /** * CKADecrypt is an instance of PKCS#11 CK_ATTRIBUTE with * type = CKA_DECRYPT and value CK_TRUE. */ public static class Decrypt extends CKAUsage { public Decrypt() { super(PKCS11Constants.CKA_DECRYPT); } } /** * CKAWrap is an instance of PKCS#11 CK_ATTRIBUTE with * type = CKA_WRAP and value CK_TRUE. */ public static class Wrap extends CKAUsage { public Wrap() { super(PKCS11Constants.CKA_WRAP); } } /** * CKAUnwrap is an instance of PKCS#11 CK_ATTRIBUTE with * type = CKA_UNWRAP and value CK_TRUE. */ public static class Unwrap extends CKAUsage { public Unwrap() { super(PKCS11Constants.CKA_UNWRAP); } } /** * CKASign is an instance of PKCS#11 CK_ATTRIBUTE with * type = CKA_SIGN and value CK_TRUE. */ public static class Sign extends CKAUsage { public Sign() { super(PKCS11Constants.CKA_SIGN); } } /** * CKASignRecover is an instance of PKCS#11 CK_ATTRIBUTE with * type = CKA_SIGN_RECOVER and value CK_TRUE. */ public static class SignRecover extends CKAUsage { public SignRecover() { super(PKCS11Constants.CKA_SIGN_RECOVER); } } /** * CKAVerify is an instance of PKCS#11 CK_ATTRIBUTE with * type = CKA_VERIFY and value CK_TRUE. */ public static class Verify extends CKAUsage { public Verify() { super(PKCS11Constants.CKA_VERIFY); } } /** * CKAVerifyRecover is an instance of PKCS#11 CK_ATTRIBUTE with * type = CKA_VERIFY_RECOVER and value CK_TRUE. */ public static class VerifyRecover extends CKAUsage { public VerifyRecover() { super(PKCS11Constants.CKA_VERIFY_RECOVER); } } /** * CKADerive is an instance of PKCS#11 CK_ATTRIBUTE with * type = CKA_DERIVE and value CK_TRUE. */ public static class Derive extends CKAUsage { public Derive() { super(PKCS11Constants.CKA_DERIVE); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/attrs/CKAValueLen.java000066400000000000000000000023341412550063600251440ustar00rootroot00000000000000package org.mozilla.jss.pkcs11.attrs; import org.mozilla.jss.pkcs11.PKCS11Constants; /** * CKAClass is an instance of a PKCS#11 CK_ATTRIBUTE with type = CKA_CLASS. */ public class CKAValueLen extends CKAttribute { private long length = 0; /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_VALUE_LEN and * default length for the key type. * * Note that when key type is not specified and/or that mechanism lacks a * default size, the corresponding PKCS#11 call will error out. */ public CKAValueLen() { super(PKCS11Constants.CKA_VALUE_LEN); } /** * Representation of a PKCS#11 CK_ATTRIBUTE with type CKA_VALUE_LEN and a * specified length. */ public CKAValueLen(long length) { this(); setLength(length); } /** * Set the length specified by this CKA_VALUE_LEN attribute. */ public void setLength(long length) { this.length = length; } /** * Get the length of this CKA_VALUE_LEN attribute. */ public long getLength() { return length; } @Override protected native void acquireNativeResources(); @Override protected native void releaseNativeResources(); } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/attrs/CKAttribute.c000066400000000000000000000153561412550063600246040ustar00rootroot00000000000000#include #include #include #include #include "CKAttribute.h" #include "StaticVoidPointer.h" #include "NativeEnclosure.h" #include "_jni/org_mozilla_jss_pkcs11_attrs_CKAClass.h" #include "_jni/org_mozilla_jss_pkcs11_attrs_CKAKeyType.h" #include "_jni/org_mozilla_jss_pkcs11_attrs_CKAUsage.h" #include "_jni/org_mozilla_jss_pkcs11_attrs_CKAValueLen.h" static const CK_BBOOL JSS_CK_TRUE = CK_TRUE; PRStatus JSS_PK11_WrapAttribute(JNIEnv *env, jobject this, void *ptr, size_t ptr_length) { jclass this_class; jfieldID field_id; jobject ptr_object; CK_ATTRIBUTE_PTR attr = calloc(1, sizeof(CK_ATTRIBUTE)); PR_ASSERT(env != NULL && this != NULL && attr != NULL); this_class = (*env)->GetObjectClass(env, this); if (this_class == NULL) { goto failure; } field_id = (*env)->GetFieldID(env, this_class, "type", "J"); if (field_id == NULL) { goto failure; } attr->type = (CK_ULONG)((*env)->GetLongField(env, this, field_id)); attr->pValue = ptr; attr->ulValueLen = ptr_length; ptr_object = JSS_PR_wrapStaticVoidPointer(env, (void **)&attr); if (ptr_object == NULL) { goto failure; } if (JSS_PR_StoreNativeEnclosure(env, this, ptr_object, sizeof(CK_ATTRIBUTE)) != PR_SUCCESS) { goto failure; } return PR_SUCCESS; failure: memset(attr, 0, sizeof(CK_ATTRIBUTE)); free(attr); return PR_FAILURE; } PRStatus JSS_PK11_UnwrapAttribute(JNIEnv *env, jobject this, CK_ATTRIBUTE_PTR *attr) { jobject ptr_obj; jlong size = 0; PR_ASSERT(env != NULL && this != NULL && attr != NULL); if (JSS_PR_LoadNativeEnclosure(env, this, &ptr_obj, &size) != PR_SUCCESS) { goto failure; } if (JSS_PR_getStaticVoidRef(env, ptr_obj, (void **)attr) != PR_SUCCESS || *attr == NULL) { goto failure; } if (size != sizeof(CK_ATTRIBUTE)) { goto failure; } return PR_SUCCESS; failure: *attr = NULL; return PR_FAILURE; } /* ===== CKA_CLASS Attribute ===== */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_attrs_CKAClass_acquireNativeResources(JNIEnv *env, jobject this) { jclass this_class; jfieldID field_id; CK_ULONG *ptr = calloc(1, sizeof(CK_ULONG)); PR_ASSERT(env != NULL && this != NULL && ptr != NULL); this_class = (*env)->GetObjectClass(env, this); if (this_class == NULL) { goto failure; } field_id = (*env)->GetFieldID(env, this_class, "value", "J"); if (field_id == NULL) { goto failure; } *ptr = (CK_ULONG)((*env)->GetLongField(env, this, field_id)); if (JSS_PK11_WrapAttribute(env, this, (void *)ptr, sizeof(*ptr)) == PR_FAILURE) { goto failure; } return; failure: memset(ptr, 0, sizeof(*ptr)); free(ptr); } JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_attrs_CKAClass_releaseNativeResources(JNIEnv *env, jobject this) { CK_ATTRIBUTE_PTR attr = NULL; if (JSS_PK11_UnwrapAttribute(env, this, &attr) != PR_SUCCESS || attr == NULL) { return; } PR_ASSERT(attr->type == CKA_CLASS); PR_ASSERT(attr->pValue != NULL); PR_ASSERT(attr->ulValueLen == sizeof(CK_ULONG)); if (attr->pValue != NULL) { memset(attr->pValue, 0, attr->ulValueLen); free(attr->pValue); } memset(attr, 0, sizeof(CK_ATTRIBUTE)); free(attr); return; } /* ===== CKA_KEY_TYPE Attribute ===== */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_attrs_CKAKeyType_acquireNativeResources(JNIEnv *env, jobject this) { jclass this_class; jfieldID field_id; CK_ULONG *ptr = calloc(1, sizeof(CK_ULONG)); PR_ASSERT(env != NULL && this != NULL && ptr != NULL); this_class = (*env)->GetObjectClass(env, this); if (this_class == NULL) { goto failure; } field_id = (*env)->GetFieldID(env, this_class, "value", "J"); if (field_id == NULL) { goto failure; } *ptr = (CK_ULONG)((*env)->GetLongField(env, this, field_id)); JSS_PK11_WrapAttribute(env, this, (void *)ptr, sizeof(*ptr)); return; failure: memset(ptr, 0, sizeof(*ptr)); free(ptr); } JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_attrs_CKAKeyType_releaseNativeResources(JNIEnv *env, jobject this) { CK_ATTRIBUTE_PTR attr = NULL; if (JSS_PK11_UnwrapAttribute(env, this, &attr) != PR_SUCCESS || attr == NULL) { return; } PR_ASSERT(attr->type == CKA_KEY_TYPE); PR_ASSERT(attr->pValue != NULL); PR_ASSERT(attr->ulValueLen == sizeof(CK_ULONG)); if (attr->pValue != NULL) { memset(attr->pValue, 0, attr->ulValueLen); free(attr->pValue); } memset(attr, 0, sizeof(CK_ATTRIBUTE)); free(attr); return; } /* ===== CKA_{ENCRYPT,DECRYPT,...} Usage Attributes ===== */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_attrs_CKAUsage_acquireNativeResources(JNIEnv *env, jobject this) { JSS_PK11_WrapAttribute(env, this, (void *)&JSS_CK_TRUE, sizeof(JSS_CK_TRUE)); } JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_attrs_CKAUsage_releaseNativeResources(JNIEnv *env, jobject this) { CK_ATTRIBUTE_PTR attr = NULL; if (JSS_PK11_UnwrapAttribute(env, this, &attr) != PR_SUCCESS || attr == NULL) { return; } /* Since the internal pValue member is always a reference to JSS_CK_TRUE, * don't free it! Only free the outer CK_ATTRIBUTE pointer. */ memset(attr, 0, sizeof(CK_ATTRIBUTE)); free(attr); } /* ===== CKA_VALUE_LEN Attribute ===== */ JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_attrs_CKAValueLen_acquireNativeResources(JNIEnv *env, jobject this) { jclass this_class; jfieldID field_id; CK_ULONG *ptr = calloc(1, sizeof(CK_ULONG)); PR_ASSERT(env != NULL && this != NULL && ptr != NULL); this_class = (*env)->GetObjectClass(env, this); if (this_class == NULL) { goto failure; } field_id = (*env)->GetFieldID(env, this_class, "length", "J"); if (field_id == NULL) { goto failure; } *ptr = (CK_ULONG)((*env)->GetLongField(env, this, field_id)); if (JSS_PK11_WrapAttribute(env, this, (void *)ptr, sizeof(*ptr)) == PR_FAILURE) { goto failure; } return; failure: memset(ptr, 0, sizeof(*ptr)); free(ptr); } JNIEXPORT void JNICALL Java_org_mozilla_jss_pkcs11_attrs_CKAValueLen_releaseNativeResources(JNIEnv *env, jobject this) { CK_ATTRIBUTE_PTR attr = NULL; if (JSS_PK11_UnwrapAttribute(env, this, &attr) != PR_SUCCESS || attr == NULL) { return; } PR_ASSERT(attr->type == CKA_VALUE_LEN); PR_ASSERT(attr->pValue != NULL); PR_ASSERT(attr->ulValueLen == sizeof(CK_ULONG)); if (attr->pValue != NULL) { memset(attr->pValue, 0, attr->ulValueLen); free(attr->pValue); } memset(attr, 0, sizeof(CK_ATTRIBUTE)); free(attr); return; } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/attrs/CKAttribute.h000066400000000000000000000003251412550063600245770ustar00rootroot00000000000000#include #include PRStatus JSS_PK11_WrapAttribute(JNIEnv *env, jobject this, void *ptr, size_t ptr_length); PRStatus JSS_PK11_UnwrapAttribute(JNIEnv *env, jobject this, CK_ATTRIBUTE_PTR *attr); jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/attrs/CKAttribute.java000066400000000000000000000022201412550063600252650ustar00rootroot00000000000000package org.mozilla.jss.pkcs11.attrs; import org.mozilla.jss.util.NativeEnclosure; /** * A CKAttribute is an instance of PKCS#11 CK_ATTRIBUTE. * * Each CK_ATTRIBUTE contains three parts: * 1. A type (type), * 2. A pointer to a value (pValue), * 3. The size of said value (ulValueLen). * * In the Java layer, CKAttribute has a member "type" to contain the type * of the CK_ATTRIBUTE. It takes on values from PKCS11Constants (pkcs11t.h * and pkcs11n.h) with prefix "CKA_". The two NativeEnclosure fields, * mPointer and mPointerSize wrap a pointer to the underlying CK_ATTRIBUTE * and its size respectively. They get allocated when open() is called, and * freed when close() is called. * * The value (numbers 2 and 3 above) get determined by the extending type, * and its corresponding native methods. Some use statically allocated values, * like CKAUsage's classes. Others are dynamically allocated pointers, such as * when referring to CK_ULONG values (as with CKAValueLen for instance). */ public abstract class CKAttribute extends NativeEnclosure { public long type; public CKAttribute(long type) { this.type = type; } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs11/pk11util.h000066400000000000000000000445051412550063600227430ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* need to include these first: * * certt.h * nspr.h * jni.h * secmodt.h */ #ifndef JSS_PK11_UTIL_H #define JSS_PK11_UTIL_H PR_BEGIN_EXTERN_C /*===================================================================== K E Y S =====================================================================*/ /*********************************************************************** * * J S S _ P K 1 1 _ w r a p P r i v K e y * privk: will be eaten by the wrapper and set to NULL. * Returns: a new PK11PrivKey, or NULL if an exception occurred. */ jobject JSS_PK11_wrapPrivKey(JNIEnv *env, SECKEYPrivateKey **privk); /*********************************************************************** * * J S S _ P K 1 1 _ w r a p P u b K e y * privk: will be eaten by the wrapper and set to NULL. * Returns: a new PK11PubKey, or NULL if an exception occurred. */ jobject JSS_PK11_wrapPubKey(JNIEnv *env, SECKEYPublicKey **pubk); /************************************************************************** * Given a PrivateKey object, extracts the SECKEYPrivateKey* and stores it * at the given address. * * privkObject: A JNI reference to a PrivateKey object. * ptr: Address of a SECKEYPrivateKey* that will receive the pointer. * Returns: PR_SUCCESS for success, PR_FAILURE if an exception was thrown. */ PRStatus JSS_PK11_getPrivKeyPtr(JNIEnv *env, jobject privkObject, SECKEYPrivateKey** ptr); /*********************************************************************** * Given a PublicKey object, extracts the SECKEYPublicKey* and stores it * at the given address. * * pubkObject: A JNI reference to a PublicKey object. * ptr: Address of a SECKEYPublicKey* that will receive the pointer. * Returns: PR_SUCCESS for success, PR_FAILURE if an exception was thrown. */ PRStatus JSS_PK11_getPubKeyPtr(JNIEnv *env, jobject pubkObject, SECKEYPublicKey** ptr); /*********************************************************************** * J S S _ P K 1 1 _ g e t S y m K e y P t r * * Given a Java PK11SymKey, extracts the C PK11SymKey and stores it at * the given address. */ PRStatus JSS_PK11_getSymKeyPtr(JNIEnv *env, jobject symKeyObject, PK11SymKey **ptr); /*********************************************************************** * * J S S _ P K 1 1 _ w r a p S y m K e y * symKey: will be stored in a Java wrapper. * Returns: a new PK11SymKey, or NULL if an exception occurred. */ jobject JSS_PK11_wrapSymKey(JNIEnv *env, PK11SymKey **symKey); /*********************************************************************** * JSS_PK11_getKeyType * * Converts a PrivateKey.KeyType object to a PKCS #11 key type. * * INPUTS * keyTypeObj * A org.mozilla.jss.crypto.PrivateKey.KeyType object. * RETURNS * The key type, or nullKey if an exception occurred. */ KeyType JSS_PK11_getKeyType(JNIEnv *env, jobject keyTypeObj); /*********************************************************************** * JSS_PK11_generateKeyPair * * Create a new key pair based on the passed in mechanism and parameters * * INPUTS * mechanism * A PKCS#11 KeyPair Mechanism * slot * Slot to generate the keypair in. * pubk * returned public key * privk * returned private key key * param * PKCS #11 mechanism parameters * temporary * boolean to say if the key is temporary or permanent * sensitive * int to say if the key should be sensitive or not (-1 is default) * extractable * int to say if the key should be extractable or not (-1 is default) * RETURNS * The SECStatus, SECSuccess of success, SECFailure on failure */ SECStatus JSS_PK11_generateKeyPair(JNIEnv *env, CK_MECHANISM_TYPE mechanism, PK11SlotInfo *slot, SECKEYPublicKey **pubk, SECKEYPrivateKey **privK, void *params, PRBool temporary, jint senstive, jint extractable); SECStatus JSS_PK11_generateKeyPair_withOpFlags(JNIEnv *env, CK_MECHANISM_TYPE mechanism, PK11SlotInfo *slot, SECKEYPublicKey **pubk, SECKEYPrivateKey **privk, void *params, PRBool temporary, jint sensitive, jint extractable, jint op_flags, jint op_flags_mask); /*===================================================================== C E R T I F I C A T E S =====================================================================*/ /****************************************************************** * * J S S _ P K 1 1 _ g e t C e r t P t r * * Given a PK11Cert object, extracts the CERTCertificate* and * stores it at the given address. * * certObject: A JNI reference to a JSS Certificate object. * ptr: Address of a CERTCertificate* that will receive the pointer. * Returns: PR_SUCCESS for success, PR_FAILURE if an exception was thrown. */ PRStatus JSS_PK11_getCertPtr(JNIEnv *env, jobject certObject, CERTCertificate **ptr); /****************************************************************** * * J S S _ P K 1 1 _ g e t C e r t S l o t P t r * * Given a PK11Cert object, extracts the PK11SlotInfo* and * stores it at the given address. * * certObject: A JNI reference to a JSS Certificate object. * ptr: Address of a PK11SlotInfo* that will receive the pointer. * Returns: PR_SUCCESS for success, PR_FAILURE if an exception was thrown. */ PRStatus JSS_PK11_getCertSlotPtr(JNIEnv *env, jobject certObject, PK11SlotInfo **ptr); /************************************************************************* * * J S S _ P K 1 1 _ f i n d C e r t A n d S l o t F r o m N i c k n a m e * * A variant of NSS's PK11_FindCertFromNickname function that also * returns a PK11SlotInfo* in *ppSlot. * * If nickname is of the format "token:nickname", the slot that * contains the specified token is returned. Otherwise the internal * key slot (which contains the permanent database token) is returned. */ CERTCertificate * JSS_PK11_findCertAndSlotFromNickname(const char *nickname, void *wincx, PK11SlotInfo **ppSlot); /*************************************************************************** * * J S S _ P K 1 1 _ f i n d C e r t s A n d S l o t F r o m N i c k n a m e * * A variant of NSS's PK11_FindCertsFromNickname function that also * returns a PK11SlotInfo* in *ppSlot. * * If nickname is of the format "token:nickname", the slot that * contains the specified token is returned. Otherwise the internal * key slot (which contains the permanent database token) is returned. */ CERTCertList * JSS_PK11_findCertsAndSlotFromNickname(char *nickname, void *wincx, PK11SlotInfo **ppSlot); /*********************************************************************** * * J S S _ P K 1 1 _ w r a p C e r t A n d S l o t A n d N i c k n a m e * * Builds a PK11Cert object from a CERTCertificate, a PK11SlotInfo, and * a nickname. * ppCert: Pointer to pointer to CERTCertificate. The CERTCertificate * will be wrapped in a Java certificate. If this fails, it * will be deleted. In any case, the caller should never worry about, * or use, this CERTCertificate again. To enforce this, *ppCert * will be set to NULL whether the functions fails or succeeds. * ppSlot: Pointer to pointer to PK11SlotInfo. The PK11SlotInfo * will be wrapped in a Java certificate. If this fails, it * will be deleted. In any case, the caller should never worry about, * or use, this PK11SlotInfo again. To enforce this, *ppSlot * will be set to NULL whether the functions fails or succeeds. * nickname: the cert instance's nickname. * Returns: a new Java PK11Cert object, or NULL if an exception was thrown. */ jobject JSS_PK11_wrapCertAndSlotAndNickname(JNIEnv *env, CERTCertificate **ppCert, PK11SlotInfo **ppSlot, const char *nickname); /**************************************************************** * * J S S _ P K 1 1 _ w r a p C e r t A n d S l o t * * Builds a PK11Cert object from a CERTCertificate and a PK11SlotInfo. * ppCert: Pointer to pointer to CERTCertificate. The CERTCertificate * will be wrapped in a Java certificate. If this fails, it * will be deleted. In any case, the caller should never worry about, * or use, this CERTCertificate again. To enforce this, *ppCert * will be set to NULL whether the functions fails or succeeds. * ppSlot: Pointer to pointer to PK11SlotInfo. The PK11SlotInfo * will be wrapped in a Java certificate. If this fails, it * will be deleted. In any case, the caller should never worry about, * or use, this PK11SlotInfo again. To enforce this, *ppSlot * will be set to NULL whether the functions fails or succeeds. * Returns: a new Java PK11Cert object, or NULL if an exception was thrown. */ jobject JSS_PK11_wrapCertAndSlot(JNIEnv *env, CERTCertificate **ppCert, PK11SlotInfo **ppSlot); /**************************************************************** * * J S S _ P K 1 1 _ w r a p C e r t * * Builds a PK11Cert object from a CERTCertificate. * ppCert: Pointer to pointer to CERTCertificate. The CERTCertificate * will be wrapped in a Java certificate. If this fails, it * will be deleted. In any case, the caller should never worry about, * or use, this CERTCertificate again. To enforce this, *ppCert * will be set to NULL whether the functions fails or succeeds. * Returns: a new Java PK11Cert object, or NULL if an exception was thrown. * * Use JSS_PK11_wrapCertAndSlot instead if it is important for the PK11Cert * object to have the correct slot pointer or the slot pointer is readily * available. */ jobject JSS_PK11_wrapCert(JNIEnv *env, CERTCertificate **ppCert); /**************************************************************** * * J S S _ P K 1 1 _ w r a p C e r t C h a i n * * Builds an array of PK11Cert objects from a CERTCertList. * ppChain: Pointer to pointer to CERTCertList. The CERTCertList * will be wrapped in a Java certificate. If this fails, it * will be deleted. In any case, the caller should never worry about, * or use, this CERTCertList again. To enforce this, *ppChain * will be set to NULL whether the functions fails or succeeds. * Returns: a new Java PK11Cert[] object, or NULL if an exception was thrown. */ jobjectArray JSS_PK11_wrapCertChain(JNIEnv *env, CERTCertList **ppChain); /*===================================================================== S T O R E S =====================================================================*/ /************************************************************************ * * J S S _ g e t S t o r e S l o t P t r * * Retrieve the PK11SlotInfo pointer of the given PK11Store. * * INPUTS * store * A reference to a Java PK11Store * slot * address of a PK11SlotInfo* that will be loaded with * the PK11SlotInfo pointer of the given token. * RETURNS * PR_SUCCESS if the operation was successful, PR_FAILURE if an * exception was thrown. */ PRStatus JSS_PK11_getStoreSlotPtr(JNIEnv *env, jobject store, PK11SlotInfo **slot); /*===================================================================== T O K E N S =====================================================================*/ /****************************************************************** ** ** J S S _ P K 1 1 _ m a k e C r y p t o T o k e n F r o m P K 1 1 ** ** Returns a new CryptoToken object, or NULL if an exception was thrown. **/ jobject JSS_PK11_makeCryptoTokenFromPK11(JNIEnv *env, jobject pk11token); /*********************************************************************** * * J S S _ P K 1 1 _ w r a p P K 1 1 T o k e n * * Create a PK11Token object from a PKCS #11 slot. * * slot is a pointer to a PKCS #11 slot, which must not be NULL. It will * be eaten by the wrapper and set to NULL. * * Returns a new PK11Token object, or NULL if an exception was thrown. */ jobject JSS_PK11_wrapPK11Token(JNIEnv *env, PK11SlotInfo **slot); /************************************************************************ * * J S S _ P K 1 1 _ g e t T o k e n S l o t P t r * * Retrieve the PK11SlotInfo pointer of the given token. * * tokenObject: A reference to a Java PK11Token * ptr: address of a PK11SlotInfo* that will be loaded with the PK11SlotInfo * pointer of the given token. * returns: PR_SUCCESS if the operation was successful, PR_FAILURE if an * exception was thrown. */ PRStatus JSS_PK11_getTokenSlotPtr(JNIEnv *env, jobject tokenObject, PK11SlotInfo **ptr); /*===================================================================== M O D U L E S =====================================================================*/ /*********************************************************************** * * J S S _ P K 1 1 _ w r a p P K 1 1 M o d u l e * * Turns a SECMODModule* C structure into a PK11Module Java object. * * INPUTS * ptr * Address of a SECMODModule *. This pointer will be copied * into the new Java object, then set to NULL. * RETURNS * A new Java PK11Module object, or NULL if an exception was thrown. * In any case, the ptr parameter is eaten. */ jobject JSS_PK11_wrapPK11Module(JNIEnv *env, SECMODModule **module); /*********************************************************************** * * J S S _ P K 1 1 _ g e t M o d u l e P t r * * Retrieve the SECMODModule pointer of the given PK11Module. * * INPUTS * module * A reference to a Java PK11Module. * ptr * Address of a SECMODModule * that will be loaded with the * SECMODModule pointer of the given PK11Module. * RETURNS * PR_FAILURE if an exception was thrown, or PR_SUCCESS if the * peration succeeded. */ PRStatus JSS_PK11_getModulePtr(JNIEnv *env, jobject module, SECMODModule **ptr); /*===================================================================== C O N T E X T S =====================================================================*/ typedef enum { SGN_CONTEXT, VFY_CONTEXT } SigContextType; typedef struct SigContextProxyStr SigContextProxy; /*********************************************************************** * J S S _ P K 1 1 _ g e t S i g C o n t e x t * * Extracts the context pointer from a ContextProxy. * proxy: a non-NULL SigContextProxy object. * ptr: address of a SGNContext* or VFYContext* where the pointer will * be stored. * type: address of a SigContextType where the type of context will * be stored. * Returns: PR_SUCCESS, unless an exception was thrown. */ PRStatus JSS_PK11_getSigContext(JNIEnv *env, jobject proxy, void**pContext, SigContextType* pType); /********************************************************************** * * J S S _ P K 1 1 _ m a k e S i g C o n t e x t P r o x y * * Wraps a context in a ContextProxy. * * ctxt: address of a SGNContext* or VFYContext* that must not be NULL. * It will be eaten by the wrapper and set to NULL. * type: the type of context, SGN_CONTEXT or VFY_CONTEXT. * Returns: a new ContextProxy object wrapping the given context, * or NULL if an exception was thrown. */ jobject JSS_PK11_wrapSigContextProxy(JNIEnv *env, void **ctxt, SigContextType type, PRArenaPool **arena); /*********************************************************************** * * J S S _ P K 1 1 _ g e t C i p h e r C o n t e x t * * Extracts the PK11Context from a CipherContextProxy. * * proxy * A CipherContextProxy. * * pContext * Address of a PK11Context*, which will be filled with the pointer * extracted from the CipherContextProxy. * * RETURNS * PR_SUCCESS for success, or PR_FAILURE if an exception was thrown. */ PRStatus JSS_PK11_getCipherContext(JNIEnv *env, jobject proxy, PK11Context **pContext); /*********************************************************************** * * J S S _ P K 1 1 _ w r a p C i p h e r C o n t e x t P r o x y * * Wraps a PK11Context in a CipherContextProxy. * * context * address of a pointer to a PK11Context, which must not be NULL. * It will be eaten by the wrapper and set to NULL, even if the * function returns NULL. * * RETURNS * A new CipherContextProxy, or NULL if an exception was thrown. */ jobject JSS_PK11_wrapCipherContextProxy(JNIEnv *env, PK11Context **context); /*===================================================================== P K C S # 1 1 H A C K S =====================================================================*/ /*********************************************************************** * * J S S _ P K 1 1 _ g e t N e w S e s s i o n * * Creates a new session. If one cannot be created, the common shared session * is returned, and *owner is set to PR_FALSE. Otherwise, the new * session is returned and *owner is set to PR_TRUE. * * slot * The slot on which to open a session. * owner * Pointer to a PRBool which will set to PR_TRUE if a new session was * created, and to PR_FALSE if the shared session was returned. * * RETURNS * A session that can be used for cryptographic operations. If *owner * is false, the session is not owned by the called but rather is shared. */ CK_SESSION_HANDLE JSS_PK11_getNewSession(PK11SlotInfo *slot, PRBool *owner); /*********************************************************************** * * J S S _ P K 1 1 _ c l o s e S e s s i o n * * Closes a session that was returned by JSS_PK11_GetNewSession. * * slot * The slot on which this session lives. * * session * The session to close. * * owner * As returned by JSS_PK11_GetNewSession. PR_TRUE if the session was * created especially for the caller, PR_FALSE if it is the common * shared session. */ void JSS_PK11_closeSession(PK11SlotInfo *slot, CK_SESSION_HANDLE session, PRBool owner); /*********************************************************************** * * J S S _ P K 1 1 _ g e t E r r o r S t r i n g * * Returns a simple error string for a given PKCS #11 error. */ char* JSS_PK11_getErrorString(CK_RV crv); /*********************************************************************** * * getSupportedWrappingMechanism * * Returns a */ CK_MECHANISM_TYPE getSupportedWrappingMechanism(JNIEnv *env, jobject algObj, PK11SlotInfo *slot); PR_END_EXTERN_C #endif jss-5.0.0/src/main/java/org/mozilla/jss/pkcs12/000077500000000000000000000000001412550063600211115ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/pkcs12/AuthenticatedSafes.java000066400000000000000000000451131412550063600255240ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs12; import java.io.CharConversionException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import javax.crypto.BadPaddingException; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.crypto.IllegalBlockSizeException; import org.mozilla.jss.crypto.JSSSecureRandom; import org.mozilla.jss.crypto.PBEAlgorithm; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.pkcs7.ContentInfo; import org.mozilla.jss.pkcs7.EncryptedContentInfo; import org.mozilla.jss.pkcs7.EncryptedData; import org.mozilla.jss.util.Password; /** * An AuthenticatedSafes, which is a SEQUENCE of * SafeContents. */ public class AuthenticatedSafes implements ASN1Value { private SEQUENCE sequence; /** * The default number of hash iterations (1) when performing PBE keygen. */ public static final int DEFAULT_ITERATIONS = 1; /** * Salt length is variable with PKCS #12. NSS uses 16 bytes, MSIE * uses 20. We'll use 20 to get the 4 extra bytes of security. */ private static final int SALT_LENGTH = 20; /** * The default PBE key generation algorithm: SHA-1 with RC2 40-bit CBC. */ public static final PBEAlgorithm DEFAULT_KEY_GEN_ALG = PBEAlgorithm.PBE_SHA1_RC2_40_CBC; // security dynamics has a weird way of packaging things, we'll // work with it for debugging private static final boolean ACCEPT_SECURITY_DYNAMICS = false; /** * Default constructor, creates an empty AuthenticatedSafes. */ public AuthenticatedSafes() { sequence = new SEQUENCE(); } /** * Creates an AuthenticatedSafes from a SEQUENCE of ContentInfo. * @param sequence A non-null sequence of ContentInfo. */ public AuthenticatedSafes(SEQUENCE sequence) { if( sequence==null) { throw new IllegalArgumentException("parameter is null"); } for( int i = 0; i < sequence.size(); i++ ) { if( ! (sequence.elementAt(i) instanceof ContentInfo) ) { throw new IllegalArgumentException( "element "+i+" of sequence is not a ContentInfo"); } } this.sequence = sequence; } /** * Returns the raw SEQUENCE which constitutes this * AuthenticatedSafes. The elements of this sequence are some * form of SafeContents, wrapped in a ContentInfo or * an EncryptedData. */ public SEQUENCE getSequence() { return sequence; } /** * Returns the size of the sequence, which is the number of SafeContents * in this AuthenticatedSafes. */ public int getSize() { return sequence.size(); } /** * Returns true if the SafeContents at the given index in the * AuthenticatedSafes is encrypted. If it is encrypted, a password * must be supplied to getSafeContentsAt when accessing * this SafeContents. */ public boolean safeContentsIsEncrypted(int index) { ContentInfo ci = (ContentInfo) sequence.elementAt(index); return ci.getContentType().equals(ContentInfo.ENCRYPTED_DATA); } /** * Returns the SafeContents at the given index in the AuthenticatedSafes, * decrypting it if necessary. * *

The algorithm used to extract encrypted SafeContents does not * conform to version 1.0 of the spec. Instead, it conforms to the * draft 1.0 spec, because this is what Communicator and MSIE seem * to conform to. This looks like an implementation error that has * become firmly entrenched to preserve interoperability. The draft * spec dictates that the encrypted content in the EncryptedContentInfo * is the DER encoding of a SafeContents. This is simple enough. The * 1.0 final spec says that the SafeContents is wrapped in a ContentInfo, * then the ContentInfo is BER encoded, then the value octets (not the * tag or length) are encrypted. No wonder people stayed with the old way. * * @param password The password to use to decrypt the SafeContents if * it is encrypted. If the SafeContents is known to not be encrypted, * this parameter can be null. If the password is incorrect, the * decoding will fail somehow, probably with an InvalidBERException, * BadPaddingException, or IllegalBlockSizeException. * @param index The index of the SafeContents to extract. * @return A SafeContents object, which is merely a * SEQUENCE of SafeBags. * @exception IllegalArgumentException If no password was provided, * but the SafeContents is encrypted. */ public SEQUENCE getSafeContentsAt(Password password, int index) throws IllegalStateException, NotInitializedException, NoSuchAlgorithmException, InvalidBERException, IOException, InvalidKeyException, InvalidAlgorithmParameterException, TokenException, IllegalBlockSizeException, BadPaddingException { ContentInfo ci = (ContentInfo) sequence.elementAt(index); if( ci.getContentType().equals(ContentInfo.ENCRYPTED_DATA) ) { // SafeContents is encrypted if( password == null ) { // can't decrypt if we don't have a password throw new IllegalStateException("No password to decode "+ "encrypted SafeContents"); } EncryptedContentInfo encCI = ((EncryptedData)ci.getInterpretedContent()). getEncryptedContentInfo(); // this should be a BER-encoded SafeContents byte[] decrypted = encCI.decrypt(password, new PasswordConverter()); //print_byte_array(decrypted); try { SEQUENCE.OF_Template seqt = new SEQUENCE.OF_Template( SafeBag.getTemplate() ); return (SEQUENCE) ASN1Util.decode(seqt, decrypted); } catch(InvalidBERException e) { if( ACCEPT_SECURITY_DYNAMICS ) { // try the security dynamics approach ContentInfo.Template cit = ContentInfo.getTemplate(); ci = (ContentInfo) ASN1Util.decode(cit, decrypted); if( ! ci.getContentType().equals(ContentInfo.DATA) ) { throw new InvalidBERException(""); } OCTET_STRING os = (OCTET_STRING) ci.getInterpretedContent(); SEQUENCE.OF_Template seqt = new SEQUENCE.OF_Template( SafeBag.getTemplate() ); return (SEQUENCE) ASN1Util.decode(seqt, os.toByteArray()); } else { throw e; } } } else if( ci.getContentType().equals(ContentInfo.DATA) ) { // This SafeContents is not encrypted SEQUENCE.OF_Template seqt = new SEQUENCE.OF_Template( SafeBag.getTemplate() ); return (SEQUENCE) ASN1Util.decode(seqt, ((OCTET_STRING)ci.getInterpretedContent()). toByteArray() ); } else { throw new InvalidBERException("AuthenticatedSafes element is"+ " neither a Data or an EncryptedData"); } } static void print_byte_array(byte[] bytes) { int online=0; for(int i=0; i < bytes.length; i++, online++) { if( online > 25 ) { System.out.println(""); online=0; } System.out.print(Integer.toHexString(bytes[i]&0xff) + " "); } System.out.println(""); } /** * Returns the decrypted content from the encrypted content info. private static byte[] decryptEncryptedContentInfo(EncryptedContentInfo eci, Password pass) throws IllegalStateException,CryptoManager.NotInitializedException, NoSuchAlgorithmException, InvalidBERException, IOException, InvalidKeyException, InvalidAlgorithmParameterException, TokenException, IllegalBlockSizeException, BadPaddingException { OCTET_STRING encryptedContent = eci.getEncryptedContent(); if( encryptedContent == null ) { return null; } // get the key gen parameters AlgorithmIdentifier algid = eci.getContentEncryptionAlgorithm(); KeyGenAlgorithm kgAlg = KeyGenAlgorithm.fromOID( algid.getOID() ); ASN1Value params = algid.getParameters(); if( params == null ) { throw new InvalidAlgorithmParameterException( "PBE algorithms require parameters"); } byte[] encodedParams = ASN1Util.encode(params); PBEParameter pbeParams = (PBEParameter) ASN1Util.decode( PBEParameter.getTemplate(), encodedParams ); PBEKeyGenParams kgp = new PBEKeyGenParams(pass, pbeParams.getSalt(), pbeParams.getIterations() ); // compute the key and IV CryptoToken token = CryptoManager.getInstance().getInternalCryptoToken(); KeyGenerator kg = token.getKeyGenerator( kgAlg ); kg.setCharToByteConverter( new PasswordConverter() ); kg.initialize( kgp ); SymmetricKey key = kg.generate(); // compute algorithm parameters EncryptionAlgorithm encAlg = keyGenAlgToEncryptionAlg(kgAlg); AlgorithmParameterSpec algParams; if( encAlg.getParameterClass().equals( IVParameterSpec.class ) ) { algParams = new IVParameterSpec( kg.generatePBE_IV() ); } else { algParams = null; } // perform the decryption Cipher cipher = token.getCipherContext( encAlg ); cipher.initDecrypt(key, algParams ); return cipher.doFinal( encryptedContent.toByteArray() ); } */ /** * Appends an unencrypted SafeContents to the end of the AuthenticatedSafes. */ public void addSafeContents(SEQUENCE safeContents) { checkSafeContents(safeContents); ContentInfo ci = new ContentInfo( ASN1Util.encode(safeContents) ); sequence.addElement(ci); } /** * Verifies that each element is a SafeBag. Throws an * IllegalArgumentException otherwise. */ private static void checkSafeContents(SEQUENCE safeContents) { int size = safeContents.size(); for( int i = 0; i < size; i++) { if( ! (safeContents.elementAt(i) instanceof SafeBag) ) { throw new IllegalArgumentException( "Element "+i+" of SafeContents is not a SafeBag"); } } } /** * Encrypts a SafeContents and adds it to the AuthenticatedSafes. * * @param keyGenAlg The algorithm used to generate a key from the password. * Must be a PBE algorithm. DEFAULT_KEY_GEN_ALG is * usually fine here. It only provides 40-bit security, but if the * private key material is packaged in its own * EncryptedPrivateKeyInfo, the security of the SafeContents * is not as important. * @param password The password to use to generate the encryption key * and IV. * @param salt The salt to use to generate the key and IV. If null is * passed in, the salt will be generated randomly, which is usually * the right thing to do. * @param iterationCount The number of hash iterations to perform when * generating the key and IV. Use DEFAULT_ITERATIONS unless * you want to be clever. * @param safeContents A SafeContents, which is a SEQUENCE of SafeBags. * Each element of the sequence must in fact be an instance of * SafeBag. */ public void addEncryptedSafeContents(PBEAlgorithm keyGenAlg, Password password, byte[] salt, int iterationCount, SEQUENCE safeContents) throws NotInitializedException, InvalidKeyException, InvalidAlgorithmParameterException, TokenException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException { try { // generate salt if necessary if( salt == null ) { // generate random salt JSSSecureRandom rand = CryptoManager.getInstance(). createPseudoRandomNumberGenerator(); salt = new byte[SALT_LENGTH]; rand.nextBytes(salt); } EncryptedContentInfo encCI = EncryptedContentInfo.createPBE(keyGenAlg, password, salt, iterationCount, new PasswordConverter(), ASN1Util.encode(safeContents)); EncryptedData encData = new EncryptedData(encCI); ContentInfo ci = new ContentInfo(encData); sequence.addElement( ci ); } catch( CharConversionException e ) { throw new RuntimeException("Unable to convert password: " + e.getMessage(), e); } } /* private static EncryptedContentInfo createEncryptedContentInfo(Password password, byte[] salt, int iterationCount, KeyGenAlgorithm keyGenAlg, SEQUENCE safeContents) throws CryptoManager.NotInitializedException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException, TokenException, BadPaddingException, IllegalBlockSizeException { try { // check key gen algorithm if( ! keyGenAlg.isPBEAlg() ) { throw new NoSuchAlgorithmException("Key generation algorithm"+ " is not a PBE algorithm"); } CryptoManager cman = CryptoManager.getInstance(); // generate salt if necessary if( salt == null ) { // generate random salt JSSSecureRandom rand = cman.createPseudoRandomNumberGenerator(); salt = new byte[SALT_LENGTH]; rand.nextBytes(salt); } // generate key CryptoToken token = cman.getInternalCryptoToken(); KeyGenerator kg = token.getKeyGenerator( keyGenAlg ); PBEKeyGenParams pbekgParams = new PBEKeyGenParams( password, salt, iterationCount); kg.setCharToByteConverter( new PasswordConverter() ); kg.initialize(pbekgParams); SymmetricKey key = kg.generate(); // generate IV EncryptionAlgorithm encAlg = keyGenAlgToEncryptionAlg(keyGenAlg); AlgorithmParameterSpec params=null; if( encAlg.getParameterClass().equals( IVParameterSpec.class ) ) { params = new IVParameterSpec( kg.generatePBE_IV() ); } // perform encryption Cipher cipher = token.getCipherContext( encAlg ); cipher.initEncrypt( key, params ); byte[] encrypted = cipher.doFinal( Cipher.pad( ASN1Util.encode(safeContents), encAlg.getBlockSize()) ); // make encryption algorithm identifier PBEParameter pbeParam = new PBEParameter( salt, iterationCount ); AlgorithmIdentifier encAlgID = new AlgorithmIdentifier( keyGenAlg.toOID(), pbeParam); // create EncryptedContentInfo EncryptedContentInfo encCI = new EncryptedContentInfo( ContentInfo.DATA, encAlgID, new OCTET_STRING(encrypted) ); return encCI; } catch( CharConversionException e ) { throw new RuntimeException("Unable to convert password: " + e.getMessage(), e); } } */ /* private static EncryptionAlgorithm keyGenAlgToEncryptionAlg(KeyGenAlgorithm kgAlg) throws NoSuchAlgorithmException { if( kgAlg==KeyGenAlgorithm.PBE_MD2_DES_CBC || kgAlg==KeyGenAlgorithm.PBE_MD5_DES_CBC || kgAlg==KeyGenAlgorithm.PBE_SHA1_DES_CBC) { return EncryptionAlgorithm.DES_CBC; } else if( kgAlg==KeyGenAlgorithm.PBE_SHA1_RC4_128 || kgAlg==KeyGenAlgorithm.PBE_SHA1_RC4_40 ) { return EncryptionAlgorithm.RC4; } else if( kgAlg==KeyGenAlgorithm.PBE_SHA1_DES3_CBC ) { return EncryptionAlgorithm.DES3_CBC; } else if( kgAlg==KeyGenAlgorithm.PBE_SHA1_RC2_128 || kgAlg==KeyGenAlgorithm.PBE_SHA1_RC2_40 ) { return EncryptionAlgorithm.RC2_CBC; } else { throw new NoSuchAlgorithmException(kgAlg.toString()); } } */ /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template class for decoding an AuthenticatedSafes from its * BER encoding. */ public static class Template implements ASN1Template { private SEQUENCE.OF_Template seqt; public Template() { seqt = new SEQUENCE.OF_Template( ContentInfo.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new AuthenticatedSafes(seq); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs12/CertBag.java000066400000000000000000000132151412550063600232650ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs12; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.EXPLICIT; import org.mozilla.jss.asn1.IA5String; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * A PKCS #12 cert bag. */ public class CertBag implements ASN1Value { /////////////////////////////////////////////////////////////////////// // Cert Type OIDs /////////////////////////////////////////////////////////////////////// private static final OBJECT_IDENTIFIER CERT_TYPES = OBJECT_IDENTIFIER.PKCS9.subBranch(22); public static final OBJECT_IDENTIFIER X509_CERT_TYPE = CERT_TYPES.subBranch(1); public static final OBJECT_IDENTIFIER SDSI_CERT_TYPE = CERT_TYPES.subBranch(2); /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private OBJECT_IDENTIFIER certType; private ANY cert; private SEQUENCE sequence; /** * Returns the certType field of the CertBag. Currently defined types are: *

    *
  • X509Certificate (X509_CERT_TYPE) *
  • SDSICertificate (SDSI_CERT_TYPE) *
*/ public OBJECT_IDENTIFIER getCertType() { return certType; } /** * Returns the cert field of the CertBag. */ public ANY getCert() { return cert; } /** * Returns the cert field of the CertBag based on its type. *
    *
  • If the type is X509_CERT_TYPE, returns * and OCTET_STRING which is the DER-encoding of an X.509 certificate. *
  • If the type is SDSI_CERT_TYPE, returns * an IA5String. *
  • For all other types, returns an ANY. *
* * @exception InvalidBERException If the cert is not encoded correctly. */ public ASN1Value getInterpretedCert() throws InvalidBERException { if( certType.equals(X509_CERT_TYPE) ) { return cert.decodeWith(OCTET_STRING.getTemplate()); } else if( certType.equals(SDSI_CERT_TYPE) ) { return cert.decodeWith(IA5String.getTemplate()); } else { return cert; } } /////////////////////////////////////////////////////////////////////// // constructors /////////////////////////////////////////////////////////////////////// /** * Creates a CertBag from a type and a cert. */ public CertBag(OBJECT_IDENTIFIER certType, ASN1Value cert) { if( certType==null || cert==null ) { throw new IllegalArgumentException("certType or cert is null"); } this.certType = certType; if( cert instanceof ANY ) { this.cert = (ANY) cert; } else { try { byte[] encoded = ASN1Util.encode(cert); this.cert = (ANY) ASN1Util.decode( ANY.getTemplate(), encoded); } catch(InvalidBERException e) { throw new RuntimeException("Unable to convert ASN1Value to ANY: "+ e.getMessage(), e); } } sequence = new SEQUENCE(); sequence.addElement(this.certType); sequence.addElement(new EXPLICIT(new Tag(0), this.cert) ); } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template class for decoding CertBags from their BER encoding. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( OBJECT_IDENTIFIER.getTemplate() ); seqt.addElement( new EXPLICIT.Template( new Tag(0), ANY.getTemplate() ) ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new CertBag( (OBJECT_IDENTIFIER) seq.elementAt(0), ((EXPLICIT)seq.elementAt(1)).getContent() ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs12/MacData.java000066400000000000000000000175151412550063600232570ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs12; import java.io.CharConversionException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.DigestException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.DigestAlgorithm; import org.mozilla.jss.crypto.HMACAlgorithm; import org.mozilla.jss.crypto.JSSMessageDigest; import org.mozilla.jss.crypto.JSSSecureRandom; import org.mozilla.jss.crypto.KeyGenAlgorithm; import org.mozilla.jss.crypto.KeyGenerator; import org.mozilla.jss.crypto.PBEKeyGenParams; import org.mozilla.jss.crypto.SymmetricKey; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.pkcs7.DigestInfo; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; import org.mozilla.jss.util.Password; public class MacData implements ASN1Value { private DigestInfo mac; private OCTET_STRING macSalt; private INTEGER macIterationCount; private static final int DEFAULT_ITERATIONS = 1; // 20 is the length of SHA-1 hash output private static final int SALT_LENGTH = 20; public DigestInfo getMac() { return mac; } public OCTET_STRING getMacSalt() { return macSalt; } public INTEGER getMacIterationCount() { return macIterationCount; } public MacData() { } /** * Creates a MacData from the given parameters. * * @param macIterationCount 1 is the default and should be used for * maximum compatibility. null can also be used, in which case * the macIterationCount will be omitted from the structure * (and the default value of 1 will be implied). */ public MacData(DigestInfo mac, OCTET_STRING macSalt, INTEGER macIterationCount) { if( mac==null || macSalt==null || macIterationCount==null ) { throw new IllegalArgumentException("null parameter"); } this.mac = mac; this.macSalt = macSalt; this.macIterationCount = macIterationCount; } /** * Creates a MacData by computing a HMAC on the given bytes. An HMAC * is a message authentication code, which is a keyed digest. It proves * not only that data has not been tampered with, but also that the * entity that created the HMAC possessed the symmetric key. * * @param password The password used to generate a key using a * PBE mechanism. * @param macSalt The salt used as input to the PBE key generation * mechanism. If null is passed in, new random salt will be created. * @param iterations The iteration count for creating the PBE key. * @param toBeMACed The data on which the HMAC will be computed. * @exception NotInitializedException If the crypto subsystem * has not been initialized yet. * @exception TokenException If an error occurs on a crypto token. */ public MacData( Password password, byte[] macSalt, int iterations, byte[] toBeMACed ) throws NotInitializedException, DigestException, TokenException, CharConversionException { CryptoManager cm = CryptoManager.getInstance(); CryptoToken token = cm.getInternalCryptoToken(); if (macSalt == null) { JSSSecureRandom rand = cm.createPseudoRandomNumberGenerator(); macSalt = new byte[SALT_LENGTH]; rand.nextBytes(macSalt); } PBEKeyGenParams params = new PBEKeyGenParams(password, macSalt, iterations); try { // generate key from password and salt KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.PBA_SHA1_HMAC); kg.setCharToByteConverter(new PasswordConverter()); kg.initialize(params); SymmetricKey key = kg.generate(); // perform the digesting JSSMessageDigest digest = token.getDigestContext(HMACAlgorithm.SHA1); digest.initHMAC(key); byte[] digestBytes = digest.digest(toBeMACed); // put everything into a DigestInfo AlgorithmIdentifier algID = new AlgorithmIdentifier(DigestAlgorithm.SHA1.toOID()); this.mac = new DigestInfo(algID, new OCTET_STRING(digestBytes)); this.macSalt = new OCTET_STRING(macSalt); this.macIterationCount = new INTEGER(iterations); } catch (NoSuchAlgorithmException e) { throw new RuntimeException("SHA-1 HMAC algorithm not found on internal " + "token: " + e.getMessage(), e); } catch (InvalidAlgorithmParameterException e) { throw new RuntimeException("Invalid PBE algorithm parameters: " + e.getMessage(), e); } catch (java.lang.IllegalStateException e) { throw new RuntimeException("Illegal state: " + e.getMessage(), e); } catch (InvalidKeyException e) { throw new RuntimeException("Invalid key: " + e.getMessage(), e); } finally { params.clear(); } } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// @Override public Tag getTag() { return TAG; } private static final Tag TAG = SEQUENCE.TAG; @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); seq.addElement(mac); seq.addElement(macSalt); if( ! macIterationCount.equals(new INTEGER(DEFAULT_ITERATIONS)) ) { // 1 is the default, only include this element if it is not // the default seq.addElement(macIterationCount); } seq.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static final Template getTemplate() { return templateInstance; } /** * A Template for decoding a MacData from its BER encoding. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( DigestInfo.getTemplate() ); seqt.addElement( OCTET_STRING.getTemplate() ); seqt.addElement( INTEGER.getTemplate(), new INTEGER(DEFAULT_ITERATIONS) ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new MacData( (DigestInfo) seq.elementAt(0), (OCTET_STRING) seq.elementAt(1), (INTEGER) seq.elementAt(2) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs12/PFX.java000066400000000000000000000443131412550063600224160ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs12; import java.io.BufferedInputStream; import java.io.CharConversionException; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.DigestException; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BMPString; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.SET; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.crypto.JSSSecureRandom; import org.mozilla.jss.crypto.PBEAlgorithm; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.pkcs7.ContentInfo; import org.mozilla.jss.pkcs7.DigestInfo; import org.mozilla.jss.pkix.cert.Certificate; import org.mozilla.jss.pkix.primitive.Attribute; import org.mozilla.jss.pkix.primitive.EncryptedPrivateKeyInfo; import org.mozilla.jss.pkix.primitive.PrivateKeyInfo; import org.mozilla.jss.util.Password; /** * The top level ASN.1 structure for a PKCS #12 blob. * *

The general procedure for creating a PFX blob is as follows:

    * *
  • Create instances of SafeBag containing things such as * private keys, certificates, or arbitrary secrets. *
  • Store the SafeBags in one or more SEQUENCEs. Each SEQUENCE is * called a SafeContents. *
  • Create an AuthenticatedSafes. Store each SafeContents into the * AuthenticatedSafes with addEncryptedSafeContents or * addSafeContents. *

    Standard procedure for browsers is for the AuthenticatedSafes to contain * two instances of SafeContents, one encrypted and the other not. * Anything you want encrypted can go in the encrypted SafeContents, * and anything you want in plaintext can go in the regular SafeContents. * Keep in mind that private key SafeBags usually consist of an * EncryptedPrivateKeyInfo, which has its own (strong) encryption, * in which case it is not essential that the SafeContents containing * the private key also be encrypted. *

  • Create a PFX containing the AuthenticatedSafes instance, using the * PFX(AuthenticatedSafes) constructor. *
  • Add a MAC to the PFX so it can be verified, using * PFX.computeMacData. *
* * To decode a PFX,
    * *
  • Use a PFX.Template to decode the ASN.1 into a * PFX object. *
  • Check the output of PFX.verifyAuthSafes to verify * the MAC on the PFX. *
  • Use PFX.getAuthSafes to extract the AuthenticatedSafes * instance. *
  • Use AuthenticatedSafes.getSafeContentsAt to grab the * SafeContents objects in the AuthenticatedSafes. *
  • Each SafeContents is a SEQUENCE of SafeBags, each of which may * contain a private key, cert, or arbitrary secret. *
*/ public class PFX implements ASN1Value { /////////////////////////////////////////////////////////////////////// // Members /////////////////////////////////////////////////////////////////////// private INTEGER version; private AuthenticatedSafes authSafes; private MacData macData; // may be null private byte[] encodedAuthSafes; // may be null // currently we are on version 3 of the standard private static final INTEGER VERSION = new INTEGER(3); /** * The default number of iterations to use when generating the MAC. * Currently, it is 1. */ public static final int DEFAULT_ITERATIONS = 1; public INTEGER getVersion() { return version; } public AuthenticatedSafes getAuthSafes() { return authSafes; } /** * Returns the MacData of this PFX, which is used to verify the contents. * This field is optional. If it is not present, null is returned. */ public MacData getMacData() { return macData; } private void setEncodedAuthSafes(byte[] encodedAuthSafes) { this.encodedAuthSafes = encodedAuthSafes; } /** * Verifies the HMAC on the authenticated safes, using the password * provided. * * @param password The password to use to compute the HMAC. * @param reason If supplied, the reason for the verification failure * will be appended to this StringBuffer. * @return true if the MAC verifies correctly, false otherwise. If * this PFX does not contain a MacData, returns false. */ public boolean verifyAuthSafes(Password password, StringBuffer reason) throws NotInitializedException { try { if (reason == null) { // this is just so we don't get a null pointer exception reason = new StringBuffer(); } if (macData == null) { reason.append("No MAC present in PFX"); return false; } if (encodedAuthSafes == null) { // We weren't decoded from a template, we were constructed, // so just verify the encoding of the AuthSafes provided to // the constructor. encodedAuthSafes = ASN1Util.encode(authSafes); } // create a new MacData based on the encoded Auth Safes DigestInfo macDataMac = macData.getMac(); MacData testMac = new MacData(password, macData.getMacSalt().toByteArray(), macData.getMacIterationCount().intValue(), encodedAuthSafes); if (testMac.getMac().equals(macDataMac)) { return true; } else { reason.append("Digests do not match"); return false; } } catch (java.security.DigestException e) { e.printStackTrace(); reason.append("A DigestException occurred"); return false; } catch (TokenException e) { reason.append("A TokenException occurred"); return false; } catch (CharConversionException e) { reason.append("An exception occurred converting the password from chars to bytes"); return false; } } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * Creates a PFX with the given parameters. */ public PFX( INTEGER version, AuthenticatedSafes authSafes, MacData macData) { if( version==null || authSafes==null ) { throw new IllegalArgumentException("null parameter"); } this.version = version; this.authSafes = authSafes; this.macData = macData; } /** * Creates a PFX with the default version. */ public PFX( AuthenticatedSafes authSafes, MacData macData ) { this( VERSION, authSafes, macData ); } /** * Creates a PFX with the default version and no MacData. The MacData * can be added later with computeMacData. * @see #computeMacData */ public PFX( AuthenticatedSafes authSafes ) { this( VERSION, authSafes, null ); } /** * Computes the macData field and adds it to the PFX. The macData field * is a Message Authentication Code of the AuthenticatedSafes, and * is used to prove the authenticity of the PFX. * * @param password The password to be used to create the password-based MAC. * @param salt The salt to be used. If null is passed in, a new salt * will be created from a random source. * @param iterationCount The iteration count for the key generation. * Use DEFAULT_ITERATIONS unless there's a need to be clever. */ public void computeMacData(Password password, byte[] salt, int iterationCount) throws NotInitializedException, DigestException, TokenException, CharConversionException { macData = new MacData( password, salt, iterationCount, ASN1Util.encode(authSafes) ); } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// @Override public Tag getTag() { return TAG; } private static final Tag TAG = SEQUENCE.TAG; @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); seq.addElement(version); seq.addElement( new ContentInfo( ASN1Util.encode(authSafes) ) ); if(macData != null) { seq.addElement(macData); } seq.encode(implicitTag, ostream); } /** * A Template for decoding a BER-encoded PFX. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = SEQUENCE.getTemplate(); seqt.addElement( INTEGER.getTemplate() ); seqt.addElement( ContentInfo.getTemplate() ); seqt.addOptionalElement( MacData.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); ContentInfo authSafesCI = (ContentInfo) seq.elementAt(1); if( ! authSafesCI.getContentType().equals(ContentInfo.DATA) ) { throw new InvalidBERException( "ContentInfo containing AuthenticatedSafes does not have"+ " content-type DATA"); } OCTET_STRING authSafesOS = (OCTET_STRING) authSafesCI.getInterpretedContent(); AuthenticatedSafes authSafes = (AuthenticatedSafes) ASN1Util.decode( AuthenticatedSafes.getTemplate(), authSafesOS.toByteArray() ); PFX pfx = new PFX( (INTEGER) seq.elementAt(0), authSafes, (MacData) seq.elementAt(2) ); // record the encoding of the auth safes so we can verify the // MAC later. We can't just re-encode the AuthSafes because // it is BER, and the re-encoding might be different from // the original encoding. pfx.setEncodedAuthSafes(authSafesOS.toByteArray()); return pfx; } } public static void main(String []args) { try { if( args.length != 2 ) { System.out.println("Usage: PFX "); System.exit(-1); } int certfile = 0; CryptoManager.initialize( args[0] ); // Decode the P12 file PFX.Template pfxt = new PFX.Template(); PFX pfx; FileInputStream fis = new FileInputStream(args[1]); try (BufferedInputStream in = new BufferedInputStream(fis, 2048)) { pfx = (PFX) pfxt.decode(in); } System.out.println("Decoded PFX"); // now peruse it for interesting info System.out.println("Version: "+pfx.getVersion()); AuthenticatedSafes authSafes = pfx.getAuthSafes(); SEQUENCE asSeq = authSafes.getSequence(); System.out.println("AuthSafes has "+ asSeq.size()+" SafeContents"); System.out.println("Enter password: "); Password pass = Password.readPasswordFromConsole(); // get new password System.out.println("Enter new password:"); Password newPass = Password.readPasswordFromConsole(); // verify the PFX StringBuffer sb = new StringBuffer(); if( pfx.verifyAuthSafes(pass, sb) ) { System.out.println("AuthSafes verifies correctly"); } else { System.out.println("AuthSafes failed to verify because: "+ sb); } // get new AuthSafes ready AuthenticatedSafes newAuthSafes = new AuthenticatedSafes(); for(int i=0; i < asSeq.size(); i++) { SEQUENCE safeContents = authSafes.getSafeContentsAt(pass,i); System.out.println("\n\nSafeContents #"+i+" has "+ safeContents.size()+" bags"); for(int j=0; j < safeContents.size(); j++) { SafeBag safeBag = (SafeBag) safeContents.elementAt(j); System.out.println("\nBag "+j+" has type "+ safeBag.getBagType() ); SET attribs = safeBag.getBagAttributes(); if( attribs == null ) { System.out.println("Bag has no attributes"); } else { for(int b=0; b < attribs.size(); b++) { Attribute a = (Attribute) attribs.elementAt(b); if( a.getType().equals(SafeBag.FRIENDLY_NAME)) { BMPString bs = (BMPString) ((ANY)a.getValues(). elementAt(0)).decodeWith( BMPString.getTemplate()); System.out.println("Friendly Name: "+bs); } else if(a.getType().equals(SafeBag.LOCAL_KEY_ID)){ OCTET_STRING os =(OCTET_STRING) ((ANY)a.getValues(). elementAt(0)).decodeWith( OCTET_STRING.getTemplate()); System.out.println("LocalKeyID:"); AuthenticatedSafes. print_byte_array(os.toByteArray()); } else { System.out.println("Unknown attribute type"); } } } ASN1Value val = safeBag.getInterpretedBagContent(); if( val instanceof PrivateKeyInfo ) { System.out.println("content is PrivateKeyInfo"); } else if( val instanceof EncryptedPrivateKeyInfo ) { EncryptedPrivateKeyInfo epki = ((EncryptedPrivateKeyInfo)val); System.out.println( "content is EncryptedPrivateKeyInfo, algoid:" + epki.getEncryptionAlgorithm().getOID()); PrivateKeyInfo pki = epki.decrypt(pass, new PasswordConverter() ); byte[] salt = new byte[20]; JSSSecureRandom rand = CryptoManager.getInstance(). getSecureRNG(); rand.nextBytes(salt); epki = EncryptedPrivateKeyInfo.createPBE( PBEAlgorithm.PBE_SHA1_DES3_CBC, newPass, salt, 1, new PasswordConverter(), pki); // replace the old safe bag with the new safeContents.insertElementAt( new SafeBag( safeBag.getBagType(), epki, safeBag.getBagAttributes()), j); safeContents.removeElementAt(j+1); } else if( val instanceof CertBag ) { System.out.println(" content is CertBag"); CertBag cb = (CertBag) val; if( cb.getCertType().equals(CertBag.X509_CERT_TYPE)) { OCTET_STRING os = (OCTET_STRING)cb.getInterpretedCert(); FileOutputStream fos = new FileOutputStream( "cert"+(certfile++)+".der"); os.encode(fos); fos.close(); Certificate cert = (Certificate) ASN1Util.decode(Certificate.getTemplate(), os.toByteArray()); cert.getInfo().print(System.out); } else { System.out.println("Unrecognized cert type"); } } else { System.out.println("content is ANY"); } } // Add the new safe contents to the authsafes if( authSafes.safeContentsIsEncrypted(i) ) { newAuthSafes.addEncryptedSafeContents( AuthenticatedSafes.DEFAULT_KEY_GEN_ALG, newPass, null, AuthenticatedSafes.DEFAULT_ITERATIONS, safeContents); } else { newAuthSafes.addSafeContents( safeContents ); } } // Create new PFX from new authsafes PFX newPfx = new PFX(newAuthSafes); newPfx.computeMacData(newPass, null, DEFAULT_ITERATIONS); FileOutputStream fos = new FileOutputStream("newjss.p12"); newPfx.encode(fos); fos.close(); } catch( Exception e ) { e.printStackTrace(); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs12/PasswordConverter.java000066400000000000000000000020161412550063600254450ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs12; import org.mozilla.jss.crypto.KeyGenerator; /** * Converts password chars to bytes. The output format is big-endian Unicode, * with two zero bytes of null-termination at the end. */ public final class PasswordConverter implements KeyGenerator.CharToByteConverter { @Override public byte[] convert(char[] chars) { byte[] bytes = new byte[ (chars.length+1) * 2 ]; int c; // char index int b; // byte index for(c=0, b=0; c < chars.length; c++) { bytes[b++] = (byte) ((chars[c] & 0xff00) >>> 8); bytes[b++] = (byte) (chars[c] & 0xff); } bytes[b++] = 0; bytes[b++] = 0; assert(b == bytes.length); return bytes; } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs12/SafeBag.java000066400000000000000000000350531412550063600232520ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs12; import java.io.CharConversionException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.DigestException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BMPString; import org.mozilla.jss.asn1.EXPLICIT; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.SET; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.crypto.JSSSecureRandom; import org.mozilla.jss.crypto.PBEAlgorithm; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.pkix.primitive.Attribute; import org.mozilla.jss.pkix.primitive.EncryptedPrivateKeyInfo; import org.mozilla.jss.pkix.primitive.PrivateKeyInfo; import org.mozilla.jss.util.AssertionException; import org.mozilla.jss.util.Password; /** * A PKCS #12 SafeBag structure. */ public final class SafeBag implements ASN1Value { /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private OBJECT_IDENTIFIER bagType; private ANY bagContent; private SET bagAttributes; // may be null public OBJECT_IDENTIFIER getBagType() { return bagType; } /** * Returns the contents of this bag as an ANY. */ public ANY getBagContent() { return bagContent; } /** * Returns the bagContent interpreted by type. * @return If type is KeyBag, a PrivateKeyInfo. *
If type is PKCS-8ShroudedKeyBag, an EncryptedPrivateKeyInfo. *
If type is CertBag, a CertBag. *
For any other type, returns an ANY. */ public ASN1Value getInterpretedBagContent() throws InvalidBERException { if( bagType.equals(KEY_BAG) ) { return bagContent.decodeWith(PrivateKeyInfo.getTemplate()); } else if( bagType.equals(PKCS8_SHROUDED_KEY_BAG)) { return bagContent.decodeWith(EncryptedPrivateKeyInfo.getTemplate()); } else if( bagType.equals(CERT_BAG) ) { return bagContent.decodeWith(CertBag.getTemplate()); } else { return bagContent; } } /** * Returns the attributes of this bag. May return null if this bag * has no attributes. Each element of the set is a * org.mozilla.jss.pkix.primitive.Attribute. */ public SET getBagAttributes() { return bagAttributes; } /////////////////////////////////////////////////////////////////////// // OIDs /////////////////////////////////////////////////////////////////////// /** * The OID branch for PKCS #12, version 1.0. */ public static final OBJECT_IDENTIFIER PKCS12_VERSION_1= OBJECT_IDENTIFIER.PKCS12.subBranch(10); /** * The OID branch for the PKCS #12 bag types. */ public static final OBJECT_IDENTIFIER PKCS12_BAG_IDS = PKCS12_VERSION_1.subBranch(1); /** * A bag containing a private key. The bag content is a KeyBag, * which is equivalent to a PKCS #8 PrivateKeyInfo */ public static final OBJECT_IDENTIFIER KEY_BAG = PKCS12_BAG_IDS.subBranch(1); /** * A bag containing a private key encrypted a la PKCS #8. The bag * content is a PKCS #8 EncryptedPrivateKeyInfo. */ public static final OBJECT_IDENTIFIER PKCS8_SHROUDED_KEY_BAG = PKCS12_BAG_IDS.subBranch(2); /** * A bag containing a certificate. The bag content is CertBag. */ public static final OBJECT_IDENTIFIER CERT_BAG = PKCS12_BAG_IDS.subBranch(3); /** * A bag containing a certificate revocation list. * The bag content is CRLBag. */ public static final OBJECT_IDENTIFIER CRL_BAG = PKCS12_BAG_IDS.subBranch(4); /** * A bag containing an arbitrary secret. The bag content is * SecretBag. */ public static final OBJECT_IDENTIFIER SECRET_BAG = PKCS12_BAG_IDS.subBranch(5); /** * A bag containing a nested SafeContent . The bag content is * SafeContents, which is merely a SEQUENCE of SafeBag. */ public static final OBJECT_IDENTIFIER SAFE_CONTENTS_BAG = PKCS12_BAG_IDS.subBranch(6); /** * A FriendlyName attribute. The value is a BMPString. */ public static final OBJECT_IDENTIFIER FRIENDLY_NAME = OBJECT_IDENTIFIER.PKCS9.subBranch(20); /** * A LocalKeyID attribute. The value is an octet string. */ public static final OBJECT_IDENTIFIER LOCAL_KEY_ID = OBJECT_IDENTIFIER.PKCS9.subBranch(21); /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * Creates a new SafeBag from its components. * * @param bagType The type of this bag. For compatibility, it should * be one of the constants defined in this class. * @param bagContent The contents of the bag. The type of this parameter * is defined by the bagType parameter. * @param bagAttributes A SET of Attributes for this SafeBag. Since * attributes are optional, this parameter may be null. */ public SafeBag(OBJECT_IDENTIFIER bagType, ASN1Value bagContent, SET bagAttributes) { if( bagType==null || bagContent==null ) { throw new IllegalArgumentException("bagType or bagContent is null"); } this.bagType = bagType; try { if( bagContent instanceof ANY ) { this.bagContent = (ANY) bagContent; } else { byte[] encoded = ASN1Util.encode(bagContent); this.bagContent = (ANY) ASN1Util.decode(ANY.getTemplate(), encoded); } } catch( InvalidBERException e ) { throw new RuntimeException("Unable to convert ASN1Value to ANY: " + e.getMessage(), e); } this.bagAttributes = bagAttributes; } /** * Creates a SafeBag that contains an X.509 Certificate. * The SafeBag will have a localKeyID attribute equal * to the SHA-1 hash of the certificate, and a friendlyName * attribute equal to the supplied string. This is the way Communicator * makes a CertBag. The same localKeyID attribute should be stored * in the matching private key bag. * * @param cert A DER-encoded X.509 certificate. * @param friendlyName Will be stored in the friendlyName * attribute of the SafeBag. Should be the nickname of the cert. */ public static SafeBag createCertBag(byte[] cert, String friendlyName) throws DigestException, NoSuchAlgorithmException, InvalidBERException { return createCertBag(cert, friendlyName, getLocalKeyIDFromCert(cert)); } /** * Creates a SafeBag that contains an X.509 Certificate. * The SafeBag will have the given localKeyID attribute, * and a friendlyName * attribute equal to the supplied string. This is the way Communicator * makes a CertBag. The same localKeyID attribute should be stored * in the matching private key bag. * * @param cert A DER-encoded X.509 certificate. * @param friendlyName Will be stored in the friendlyName * attribute of the SafeBag. Should be the nickname of the cert. * @param localKeyID The bytes to used for the localKeyID. These should * be obtained from the getLocalKeyIDFromCert method. * @exception InvalidBERException If the cert is not a valid DER encoding. * @see #getLocalKeyIDFromCert */ public static SafeBag createCertBag(byte[] cert, String friendlyName, byte[] localKeyID) throws InvalidBERException { try { // create CertBag CertBag cb = new CertBag(CertBag.X509_CERT_TYPE, new ANY(cert) ); // setup attributes SET attributes = new SET(); // friendly name should be cert nickname attributes.addElement(new Attribute( FRIENDLY_NAME, new BMPString(friendlyName) )); attributes.addElement( new Attribute( LOCAL_KEY_ID, new OCTET_STRING(localKeyID) )); return new SafeBag(CERT_BAG, cb, attributes); } catch( CharConversionException e ) { throw new AssertionException("CharConversionException converting"+ " Unicode to BMPString"); } } /** * Computes the LocalKeyID attribute that should be stored with a key * and certificate. * * @param derCert A DER-encoded X.509 certificate. * @return The SHA-1 hash of the cert, which should be used as the * localKeyID attribute for the cert's SafeBag. */ public static final byte[] getLocalKeyIDFromCert(byte[] derCert) throws DigestException, NoSuchAlgorithmException { MessageDigest digester = MessageDigest.getInstance("SHA-1"); return digester.digest(derCert); } /** * Creates a SafeBag containing a PKCS-8ShroudedKeyBag, which is * an EncryptedPrivateKeyInfo. The key will be encrypted using * a triple-DES PBE algorithm, using the supplied password. * * @param privk The PrivateKeyInfo containing the private key. * @param friendlyName The nickname for the key; should be the same * as the nickname of the associated cert. * @param localKeyID The localKeyID for the key; should be the same as * the localKeyID of the associated cert. * @param password The password used to encrypt the private key. */ public static SafeBag createEncryptedPrivateKeyBag(PrivateKeyInfo privk, String friendlyName, byte[] localKeyID, Password password) throws NotInitializedException, TokenException { try { PBEAlgorithm pbeAlg = PBEAlgorithm.PBE_SHA1_DES3_CBC; final int DEFAULT_ITERATIONS = 1; byte[] salt = new byte[pbeAlg.getSaltLength()]; JSSSecureRandom rand = CryptoManager.getInstance().getSecureRNG(); rand.nextBytes(salt); EncryptedPrivateKeyInfo epki= EncryptedPrivateKeyInfo.createPBE( PBEAlgorithm.PBE_SHA1_DES3_CBC, password, salt, DEFAULT_ITERATIONS, new PasswordConverter(), privk); SET attributes = new SET(); attributes.addElement(new Attribute( FRIENDLY_NAME, new BMPString(friendlyName) )); attributes.addElement( new Attribute( LOCAL_KEY_ID, new OCTET_STRING(localKeyID) )); return new SafeBag(PKCS8_SHROUDED_KEY_BAG , epki, attributes); } catch(java.security.NoSuchAlgorithmException e) { throw new AssertionException( "Unable to find PBE algorithm: "+e); } catch(java.security.InvalidKeyException e) { throw new AssertionException( "InvalidKeyException while creating EncryptedContentInfo: "+e); } catch(java.security.InvalidAlgorithmParameterException e) { throw new AssertionException( "InvalidAlgorithmParameterException while creating"+ " EncryptedContentInfo: "+e); } catch(java.io.CharConversionException e) { throw new AssertionException( "CharConversionException while creating EncryptedContentInfo: "+ e); } } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); seq.addElement( bagType ); seq.addElement( new EXPLICIT(new Tag(0), bagContent) ); if( bagAttributes!=null ) { seq.addElement( bagAttributes ); } seq.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A template for decoding SafeBags. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( OBJECT_IDENTIFIER.getTemplate() ); seqt.addElement( new EXPLICIT.Template( new Tag(0), ANY.getTemplate() ) ); seqt.addOptionalElement( new SET.OF_Template( Attribute.getTemplate() ) ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { try { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new SafeBag( (OBJECT_IDENTIFIER) seq.elementAt(0), ((EXPLICIT)seq.elementAt(1)).getContent(), (SET) seq.elementAt(2) ); } catch( InvalidBERException e ) { throw new InvalidBERException(e, "SafeBag"); } } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs12/SecretBag.java000066400000000000000000000102261412550063600236140ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs12; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.EXPLICIT; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; public class SecretBag implements ASN1Value { /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private OBJECT_IDENTIFIER secretType; private ANY secret; private SEQUENCE sequence; /** * Returns the type of secret stored in the SecretBag. */ public OBJECT_IDENTIFIER getSecretType() { return secretType; } /** * Returns the secret stored in the SecretBag. */ public ANY getSecret() { return secret; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * Creates a SecretBag with the given secret type and secret. Neither * may be null. */ public SecretBag(OBJECT_IDENTIFIER secretType, ASN1Value secret) { if( secretType==null || secret==null ) { throw new IllegalArgumentException("SecretBag parameter is null"); } this.secretType = secretType; if( secret instanceof ANY ) { this.secret = (ANY) secret; } else { byte[] encoded = ASN1Util.encode(secret); try { this.secret = (ANY) ASN1Util.decode(ANY.getTemplate(), encoded); } catch(InvalidBERException e) { throw new RuntimeException("Unable to convert ASN1Value to ANY: " + e.getMessage(), e); } } sequence = new SEQUENCE(); sequence.addElement(secretType); sequence.addElement( new EXPLICIT(new Tag(0), this.secret) ); } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template class for decoding SecretBags from BER. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( OBJECT_IDENTIFIER.getTemplate() ); seqt.addElement( new EXPLICIT.Template( new Tag(0), ANY.getTemplate()) ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new SecretBag( (OBJECT_IDENTIFIER)seq.elementAt(0), ((EXPLICIT)seq.elementAt(1)).getContent() ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs12/package.html000066400000000000000000000005321412550063600233720ustar00rootroot00000000000000 Creating and interpreting PKCS #12 blobs. The PFX class is the top-level structure of a PKCS #12 blob. jss-5.0.0/src/main/java/org/mozilla/jss/pkcs7/000077500000000000000000000000001412550063600210355ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/pkcs7/Attribute.java000066400000000000000000000061611412550063600236470ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs7; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.SET; import org.mozilla.jss.asn1.Tag; /** * An Attribute, which has the following ASN.1 * definition (roughly): *
 *      Attribute ::= SEQUENCE {
 *          type        OBJECT IDENTIFIER,
 *          value       SET }
 * 
*/ public class Attribute implements ASN1Value { private OBJECT_IDENTIFIER type; private SET values; public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } public Attribute(OBJECT_IDENTIFIER type, SET values) { this.type = type; this.values = values; } public Attribute(OBJECT_IDENTIFIER type, ASN1Value value) { this.type = type; this.values = new SET(); values.addElement(value); } public OBJECT_IDENTIFIER getType() { return type; } /** * If this AVA was constructed, returns the SET of ASN1Values passed to the * constructor. If this Attribute was decoded with an Attribute.Template, * returns a SET of ANYs. */ public SET getValues() { return values; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicit, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); seq.addElement(type); seq.addElement(values); seq.encode(implicit, ostream); } public static Template getTemplate() { return templateInstance; } private static Template templateInstance = new Template(); /** * A Template for decoding an Attribute. */ public static class Template implements ASN1Template { @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicit, InputStream istream) throws IOException, InvalidBERException { SEQUENCE.Template seqt = new SEQUENCE.Template(); seqt.addElement( new OBJECT_IDENTIFIER.Template() ); seqt.addElement( new SET.OF_Template(new ANY.Template())); SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); // The template should have enforced this assert(seq.size() == 2); return new Attribute( (OBJECT_IDENTIFIER) seq.elementAt(0), (SET) seq.elementAt(1)); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs7/ContentInfo.java000066400000000000000000000177431412550063600241420ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs7; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.EXPLICIT; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * A PKCS #7 ContentInfo structure. */ public class ContentInfo implements ASN1Value { public static final Tag TAG = SEQUENCE.TAG; // XXX is this right? public static OBJECT_IDENTIFIER DATA = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 1 }); public static OBJECT_IDENTIFIER SIGNED_DATA = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 2 }); public static OBJECT_IDENTIFIER ENVELOPED_DATA = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 3 }); public static OBJECT_IDENTIFIER SIGNED_AND_ENVELOPED_DATA = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 4 }); public static OBJECT_IDENTIFIER DIGESTED_DATA = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 5 }); public static OBJECT_IDENTIFIER ENCRYPTED_DATA = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 6 }); private OBJECT_IDENTIFIER contentType; private ANY content; private SEQUENCE sequence = new SEQUENCE(); /** * Creates a ContentInfo with the given type and content. * * @param contentType The contentType of the ContentInfo. * @param content The content of the ContentInfo. May be null * to signify that the optional content field is not present. */ public ContentInfo(OBJECT_IDENTIFIER contentType, ASN1Value content) { this.contentType = contentType; sequence.addElement(contentType); if (content != null) { if( content instanceof ANY ) { this.content = (ANY) content; } else { // convert content to ANY try { this.content = (ANY) ASN1Util.decode(ANY.getTemplate(), ASN1Util.encode(content) ); } catch(InvalidBERException e) { throw new RuntimeException("Unable to convert " + "ASN1Value to ANY: " + e.getMessage(), e); } } sequence.addElement(new EXPLICIT(new Tag(0),content) ); } } /** * Creates a ContentInfo of type data. */ public ContentInfo(byte[] data) { this( DATA, new OCTET_STRING(data) ); } /** * Creates a ContentInfo of type signedData. */ public ContentInfo(SignedData sd) { this( SIGNED_DATA, sd); } /** * Creates a ContentInfo of type envelopedData. */ public ContentInfo(EnvelopedData ed) { this( ENVELOPED_DATA, ed ); } /** * Creates a ContentInfo of type signedAndEnvelopedData. */ public ContentInfo(SignedAndEnvelopedData sed) { this( SIGNED_AND_ENVELOPED_DATA, sed ); } /** * Creates a ContentInfo of type digestedData. */ public ContentInfo(DigestedData dd) { this( DIGESTED_DATA, dd ); } /** * Creates a ContentInfo of type encryptedData. */ public ContentInfo(EncryptedData ed) { this( ENCRYPTED_DATA, ed ); } /** * Returns the contentType field, which determines what kind of content * is contained in this ContentInfo. It will usually be one of the six * predefined types, but may also be a user-defined type. */ public OBJECT_IDENTIFIER getContentType() { return contentType; } /** * Returns true if the content field is present. */ public boolean hasContent() { return (content != null); } /** * Returns the content, interpreted based on its type. If there is no * content, null is returned. *

If the contentType is * one of the six standard types, the returned object will be of that * type. For example, if the ContentInfo has contentType signedData, * a SignedData object will be returned. If the contentType is data, * an OCTET_STRING will be returned. *

If the contentType is not one of the six standard types, * the returned object will be an ANY. */ public ASN1Value getInterpretedContent() throws InvalidBERException { if(contentType.equals(DATA)) { return content.decodeWith( new OCTET_STRING.Template() ); } else if( contentType.equals(SIGNED_DATA) ) { return content.decodeWith( new SignedData.Template() ); } else if( contentType.equals(ENVELOPED_DATA) ) { return content.decodeWith( new EnvelopedData.Template()); } else if( contentType.equals(SIGNED_AND_ENVELOPED_DATA) ) { return content.decodeWith( new SignedAndEnvelopedData.Template() ); } else if( contentType.equals(DIGESTED_DATA) ) { return content.decodeWith( new DigestedData.Template() ); } else if( contentType.equals(ENCRYPTED_DATA) ) { return content.decodeWith( new EncryptedData.Template()); } else { // unknown type return content; } } /** * Returns the content encoded as an ANY. If there is no content, * null is returned. */ public ANY getContent() { return content; } @Override public void encode(OutputStream ostream) throws IOException { encode(getTag(),ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag,ostream); } @Override public Tag getTag() { return ContentInfo.TAG; } /** * Returns a singleton instance of a decoding template for ContentInfo. */ public static Template getTemplate() { return templateInstance; } private static Template templateInstance = new Template(); /** * A template for decoding a ContentInfo blob * */ public static class Template implements ASN1Template { @Override public boolean tagMatch(Tag tag) { return (tag.equals(ContentInfo.TAG)); } private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement(new OBJECT_IDENTIFIER.Template()); seqt.addOptionalElement( new EXPLICIT.Template( new Tag(0), new ANY.Template() )); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(ContentInfo.TAG,istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream ) throws IOException, InvalidBERException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); assert(seq.size() == 2); ASN1Value content; if( seq.elementAt(1) == null ) { content = null; } else { content = ((EXPLICIT)seq.elementAt(1)).getContent(); } return new ContentInfo( (OBJECT_IDENTIFIER) seq.elementAt(0), content ); } } // end of template } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs7/DigestInfo.java000066400000000000000000000072671412550063600237470ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs7; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; public class DigestInfo implements ASN1Value { private AlgorithmIdentifier digestAlgorithm; private OCTET_STRING digest; private SEQUENCE sequence; public DigestInfo(AlgorithmIdentifier digestAlgorithm, OCTET_STRING digest){ if( digestAlgorithm==null || digest==null ) { throw new IllegalArgumentException(); } sequence = new SEQUENCE(); this.digestAlgorithm = digestAlgorithm; sequence.addElement(digestAlgorithm); this.digest = digest; sequence.addElement(digest); } public AlgorithmIdentifier getDigestAlgorithm() { return digestAlgorithm; } public OCTET_STRING getDigest() { return digest; } private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public boolean equals(Object obj) { if( obj==null || !(obj instanceof DigestInfo)) { return false; } DigestInfo di = (DigestInfo)obj; return byteArraysAreSame(di.digest.toByteArray(), digest.toByteArray()); } /** * Compares two non-null byte arrays. Returns true if they are identical, * false otherwise. */ private static boolean byteArraysAreSame(byte[] left, byte[] right) { assert(left!=null && right!=null); if( left.length != right.length ) { return false; } for(int i = 0 ; i < left.length ; i++ ) { if( left[i] != right[i] ) { return false; } } return true; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A class for decoding the BER encoding of a DigestInfo. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( AlgorithmIdentifier.getTemplate()); seqt.addElement( OCTET_STRING.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream ostream) throws InvalidBERException, IOException { return decode(TAG, ostream); } @Override public ASN1Value decode(Tag implicitTag, InputStream ostream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, ostream); return new DigestInfo( (AlgorithmIdentifier) seq.elementAt(0), (OCTET_STRING) seq.elementAt(1) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs7/DigestedData.java000066400000000000000000000101441412550063600242220ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs7; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; public class DigestedData implements ASN1Value { /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private INTEGER version; private AlgorithmIdentifier digestAlgorithm; private ContentInfo contentInfo; private OCTET_STRING digest; private SEQUENCE sequence; // for DER encoding public INTEGER getVersion() { return version; } public AlgorithmIdentifier getDigestAlgorithm() { return digestAlgorithm; } public ContentInfo getContentInfo() { return contentInfo; } public OCTET_STRING getDigest() { return digest; } /////////////////////////////////////////////////////////////////////// // constructors /////////////////////////////////////////////////////////////////////// public DigestedData(INTEGER version, AlgorithmIdentifier digestAlgorithm, ContentInfo contentInfo, OCTET_STRING digest) { if( version==null || digestAlgorithm==null || contentInfo==null || digest==null ) { throw new IllegalArgumentException("DigestedData constructor" +" parameter is null"); } this.version = version; this.digestAlgorithm = digestAlgorithm; this.contentInfo = contentInfo; this.digest = digest; sequence = new SEQUENCE(); sequence.addElement(version); sequence.addElement(digestAlgorithm); sequence.addElement(contentInfo); sequence.addElement(digest); } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } /** * A Template for decoding BER-encoded DigestData items. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( INTEGER.getTemplate() ); seqt.addElement( AlgorithmIdentifier.getTemplate() ); seqt.addElement( ContentInfo.getTemplate() ); seqt.addElement( OCTET_STRING.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new DigestedData( (INTEGER) seq.elementAt(0), (AlgorithmIdentifier) seq.elementAt(1), (ContentInfo) seq.elementAt(2), (OCTET_STRING) seq.elementAt(3) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs7/EncryptedContentInfo.java000066400000000000000000000327471412550063600260210ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs7; import java.io.CharConversionException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.BadPaddingException; import javax.crypto.spec.RC2ParameterSpec; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.EXPLICIT; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.crypto.Cipher; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.EncryptionAlgorithm; import org.mozilla.jss.crypto.IVParameterSpec; import org.mozilla.jss.crypto.IllegalBlockSizeException; import org.mozilla.jss.crypto.KeyGenAlgorithm; import org.mozilla.jss.crypto.KeyGenerator; import org.mozilla.jss.crypto.PBEAlgorithm; import org.mozilla.jss.crypto.PBEKeyGenParams; import org.mozilla.jss.crypto.SymmetricKey; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; import org.mozilla.jss.pkix.primitive.PBEParameter; import org.mozilla.jss.util.Password; /** * The PKCS #7 type EncryptedContentInfo, which encapsulates * encrypted data. */ public class EncryptedContentInfo implements ASN1Value { /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private OBJECT_IDENTIFIER contentType; private AlgorithmIdentifier contentEncryptionAlgorithm; private OCTET_STRING encryptedContent; // may be null private SEQUENCE sequence = new SEQUENCE(); public OBJECT_IDENTIFIER getContentType() { return contentType; } public AlgorithmIdentifier getContentEncryptionAlgorithm() { return contentEncryptionAlgorithm; } public OCTET_STRING getEncryptedContent() { return encryptedContent; } public boolean hasEncryptedContent() { return (encryptedContent!=null); } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * Create a EnvelopedData ASN1 object. */ public EncryptedContentInfo( OBJECT_IDENTIFIER contentType, AlgorithmIdentifier contentEncryptionAlgorithm, OCTET_STRING encryptedContent) { this(contentType, contentEncryptionAlgorithm, encryptedContent, false); } public EncryptedContentInfo( OBJECT_IDENTIFIER contentType, AlgorithmIdentifier contentEncryptionAlgorithm, OCTET_STRING encryptedContent, boolean createHackedCRSCompatibleECI) { this.contentType = contentType; this.contentEncryptionAlgorithm = contentEncryptionAlgorithm; this.encryptedContent = encryptedContent; sequence.addElement(contentType); sequence.addElement(contentEncryptionAlgorithm); if(encryptedContent != null) { if (createHackedCRSCompatibleECI) { sequence.addElement(new EXPLICIT(new Tag(0), encryptedContent)); } else { sequence.addElement(new Tag(0), encryptedContent); } } } public static EncryptedContentInfo createCRSCompatibleEncryptedContentInfo(OBJECT_IDENTIFIER contentType, AlgorithmIdentifier contentEncryptionAlgorithm, OCTET_STRING encryptedContent) { return new EncryptedContentInfo(contentType, contentEncryptionAlgorithm, encryptedContent, true); } /////////////////////////////////////////////////////////////////////// // Crypto shortcuts /////////////////////////////////////////////////////////////////////// /** * Creates a new EncryptedContentInfo, where the data is encrypted * with a password-based key. * * @param keyGenAlg The algorithm for generating a symmetric key from * a password, salt, and iteration count. * @param password The password to use in generating the key. * @param salt The salt to use in generating the key. * @param iterationCount The number of hashing iterations to perform * while generating the key. * @param charToByteConverter The mechanism for converting the characters * in the password into bytes. If null, the default mechanism * will be used, which is UTF8. * @param toBeEncrypted The bytes to be encrypted and stored in the * EncryptedContentInfo. Before they are encrypted, they will be * padded using PKCS padding. */ public static EncryptedContentInfo createPBE(PBEAlgorithm keyGenAlg, Password password, byte[] salt, int iterationCount, KeyGenerator.CharToByteConverter charToByteConverter, byte[] toBeEncrypted) throws NotInitializedException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException, TokenException, CharConversionException { try { // check key gen algorithm if( ! (keyGenAlg instanceof PBEAlgorithm) ) { throw new NoSuchAlgorithmException("Key generation algorithm"+ " is not a PBE algorithm"); } PBEAlgorithm pbeAlg = keyGenAlg; CryptoManager cman = CryptoManager.getInstance(); // generate key CryptoToken token = cman.getInternalCryptoToken(); KeyGenerator kg = token.getKeyGenerator( keyGenAlg ); PBEKeyGenParams pbekgParams = new PBEKeyGenParams( password, salt, iterationCount); if( charToByteConverter != null ) { kg.setCharToByteConverter( charToByteConverter ); } kg.initialize(pbekgParams); SymmetricKey key = kg.generate(); // generate IV EncryptionAlgorithm encAlg = pbeAlg.getEncryptionAlg(); AlgorithmParameterSpec params=null; Class [] paramClasses = encAlg.getParameterClasses(); for (int i = 0; i < paramClasses.length; i ++) { if ( paramClasses[i].equals( javax.crypto.spec.IvParameterSpec.class ) ) { params = new IVParameterSpec(kg.generatePBE_IV()); break; } else if ( paramClasses[i].equals( RC2ParameterSpec.class ) ) { params = new RC2ParameterSpec(key.getStrength(), kg.generatePBE_IV()); break; } } // perform encryption Cipher cipher = token.getCipherContext( encAlg ); cipher.initEncrypt( key, params ); byte[] encrypted = cipher.doFinal( Cipher.pad( toBeEncrypted, encAlg.getBlockSize()) ); // make encryption algorithm identifier PBEParameter pbeParam = new PBEParameter( salt, iterationCount ); AlgorithmIdentifier encAlgID = new AlgorithmIdentifier( keyGenAlg.toOID(), pbeParam); // create EncryptedContentInfo EncryptedContentInfo encCI = new EncryptedContentInfo( ContentInfo.DATA, encAlgID, new OCTET_STRING(encrypted) ); return encCI; } catch( IllegalBlockSizeException e ) { throw new RuntimeException("IllegalBlockSizeException in EncryptedContentInfo" +".createPBE: " + e.getMessage(), e); } catch( BadPaddingException e ) { throw new RuntimeException("BadPaddingException in EncryptedContentInfo" +".createPBE: " + e.getMessage(), e); } } /** * Decrypts the content of an EncryptedContentInfo encrypted with a * PBE key. * * @param pass The password to use in generating the PBE decryption key. * @param charToByteConverter The converter for converting the password * characters into bytes. May be null to use the default. * @return The decrypted contents of the EncryptedContentInfo. The contents * are first unpadded using the PKCS padding mechanism. */ public byte[] decrypt(Password pass, KeyGenerator.CharToByteConverter charToByteConverter) throws IllegalStateException,NotInitializedException, NoSuchAlgorithmException, InvalidBERException, IOException, InvalidKeyException, InvalidAlgorithmParameterException, TokenException, IllegalBlockSizeException, BadPaddingException { if( encryptedContent == null ) { return null; } // get the key gen parameters AlgorithmIdentifier algid = contentEncryptionAlgorithm; KeyGenAlgorithm kgAlg = KeyGenAlgorithm.fromOID( algid.getOID() ); if( !(kgAlg instanceof PBEAlgorithm) ) { throw new NoSuchAlgorithmException("KeyGenAlgorithm is not a"+ " PBE algorithm"); } ASN1Value params = algid.getParameters(); if( params == null ) { throw new InvalidAlgorithmParameterException( "PBE algorithms require parameters"); } PBEParameter pbeParams; if( params instanceof PBEParameter) { pbeParams = (PBEParameter) params; } else { byte[] encodedParams = ASN1Util.encode(params); pbeParams = (PBEParameter) ASN1Util.decode( PBEParameter.getTemplate(), encodedParams ); } PBEKeyGenParams kgp = new PBEKeyGenParams(pass, pbeParams.getSalt(), pbeParams.getIterations() ); try { // compute the key and IV CryptoToken token = CryptoManager.getInstance().getInternalCryptoToken(); KeyGenerator kg = token.getKeyGenerator( kgAlg ); if( charToByteConverter != null ) { kg.setCharToByteConverter( charToByteConverter ); } kg.initialize( kgp ); SymmetricKey key = kg.generate(); // compute algorithm parameters EncryptionAlgorithm encAlg = ((PBEAlgorithm)kgAlg).getEncryptionAlg(); AlgorithmParameterSpec algParams = null; Class [] paramClasses = encAlg.getParameterClasses(); for (int i = 0; i < paramClasses.length; i ++) { if ( paramClasses[i].equals( javax.crypto.spec.IvParameterSpec.class ) ) { algParams = new IVParameterSpec( kg.generatePBE_IV() ); break; } else if ( paramClasses[i].equals(RC2ParameterSpec.class ) ) { algParams = new RC2ParameterSpec(key.getStrength(), kg.generatePBE_IV()); break; } } // perform the decryption Cipher cipher = token.getCipherContext( encAlg ); cipher.initDecrypt(key, algParams); return Cipher.unPad(cipher.doFinal( encryptedContent.toByteArray() )); } finally { kgp.clear(); } } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(getTag(),ostream); } @Override public void encode(Tag tag, OutputStream ostream) throws IOException { sequence.encode(tag,ostream); } public static Template getTemplate() { return templateInstance; } private static final Template templateInstance = new Template(); /** * A template file for decoding a EnvelopedData blob * */ public static class Template implements ASN1Template { @Override public boolean tagMatch(Tag tag) { return (tag.equals(EncryptedContentInfo.TAG)); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG,istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { SEQUENCE.Template seqt = new SEQUENCE.Template(); seqt.addElement(new OBJECT_IDENTIFIER.Template()); seqt.addElement(new AlgorithmIdentifier.Template()); seqt.addOptionalElement(new Tag(0), new OCTET_STRING.Template()); SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); assert(seq.size() ==3); return new EncryptedContentInfo( (OBJECT_IDENTIFIER) seq.elementAt(0), (AlgorithmIdentifier) seq.elementAt(1), (OCTET_STRING) seq.elementAt(2) ); } } // end of template } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs7/EncryptedData.java000066400000000000000000000103511412550063600244270ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs7; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * The PKCS #7 structure EncryptedData. */ public class EncryptedData implements ASN1Value { /////////////////////////////////////////////////////////////////////// // Members /////////////////////////////////////////////////////////////////////// private INTEGER version; private EncryptedContentInfo encryptedContentInfo; private SEQUENCE sequence; /** * The default version number. This should always be used unless * you really know what you are doing. */ public static final INTEGER DEFAULT_VERSION = new INTEGER(0); /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * Creates a new EncryptedData. * * @param version Should usually be DEFAULT_VERSION unless you are being * very clever. */ public EncryptedData( INTEGER version, EncryptedContentInfo encryptedContentInfo ) { if( version == null || encryptedContentInfo == null ) { throw new IllegalArgumentException("null parameter"); } sequence = new SEQUENCE(); this.version = version; sequence.addElement(version); this.encryptedContentInfo = encryptedContentInfo; sequence.addElement(encryptedContentInfo); } /** * Creates an EncryptedData with the default version. */ public EncryptedData( EncryptedContentInfo encryptedContentInfo ) { this( DEFAULT_VERSION, encryptedContentInfo ); } /////////////////////////////////////////////////////////////////////// // Accessor Methods /////////////////////////////////////////////////////////////////////// public INTEGER getVersion() { return version; } public EncryptedContentInfo getEncryptedContentInfo() { return encryptedContentInfo; } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } public static Template getTemplate() { return templateInstance; } private static final Template templateInstance = new Template(); /** * A Template for decoding EncryptedData items. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( INTEGER.getTemplate() ); seqt.addElement( EncryptedContentInfo.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new EncryptedData( (INTEGER) seq.elementAt(0), (EncryptedContentInfo) seq.elementAt(1) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs7/EnvelopedData.java000066400000000000000000000063701412550063600244210ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs7; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.SET; import org.mozilla.jss.asn1.Tag; public class EnvelopedData implements ASN1Value { public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } private INTEGER version; private SET recipientInfos; private EncryptedContentInfo encryptedContentInfo; private SEQUENCE sequence = new SEQUENCE(); public INTEGER getVersion() { return version; } public SET getRecipientInfos() { return recipientInfos; } public EncryptedContentInfo getEncryptedContentInfo() { return encryptedContentInfo; } /** * Create a EnvelopedData ASN1 object. */ public EnvelopedData( INTEGER version, SET recipientInfos, EncryptedContentInfo encryptedContentInfo) { this.version = version; this.recipientInfos = recipientInfos; this.encryptedContentInfo = encryptedContentInfo; sequence.addElement(version); sequence.addElement(recipientInfos); sequence.addElement(encryptedContentInfo); } @Override public void encode(OutputStream ostream) throws IOException { encode(getTag(),ostream); } @Override public void encode(Tag tag, OutputStream ostream) throws IOException { sequence.encode(tag,ostream); } /** * A template file for decoding a EnvelopedData blob * */ public static class Template implements ASN1Template { public Tag getTag() { return EnvelopedData.TAG; } @Override public boolean tagMatch(Tag tag) { return (tag.equals(EnvelopedData.TAG)); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(getTag(),istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { SEQUENCE.Template seqt = new SEQUENCE.Template(); seqt.addElement(new INTEGER.Template()); seqt.addElement(new SET.OF_Template(new RecipientInfo.Template())); seqt.addElement(new EncryptedContentInfo.Template()); SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); assert(seq.size() ==3); return new EnvelopedData( (INTEGER) seq.elementAt(0), (SET) seq.elementAt(1), (EncryptedContentInfo) seq.elementAt(2) ); } } // end of template } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs7/IssuerAndSerialNumber.java000066400000000000000000000075111412550063600261120ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs7; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.pkix.primitive.Name; /** * An issuer name and serial number, used to uniquely identify a certificate. */ public class IssuerAndSerialNumber implements ASN1Value { /////////////////////////////////////////////////////////////////////// // Members /////////////////////////////////////////////////////////////////////// private Name issuer; private INTEGER serialNumber; private SEQUENCE sequence; /////////////////////////////////////////////////////////////////////// // Construction /////////////////////////////////////////////////////////////////////// /** * Constructs an IssuerAndSerialNumber from its components. * * @param issuer Must not be null. * @param serialNumber must not be null. */ public IssuerAndSerialNumber(Name issuer, INTEGER serialNumber) { if(issuer==null || serialNumber==null) { throw new IllegalArgumentException(); } sequence = new SEQUENCE(); this.issuer = issuer; sequence.addElement(issuer); this.serialNumber = serialNumber; sequence.addElement(serialNumber); } /////////////////////////////////////////////////////////////////////// // accessors /////////////////////////////////////////////////////////////////////// public Name getIssuer() { return issuer; } public INTEGER getSerialNumber() { return serialNumber; } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// static Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } /** * Returns a singleton template instance. */ public static Template getTemplate() { return templateInstance; } private static Template templateInstance = new Template(); /** * A template for decoding an IssuerAndSerialNumber from its BER encoding. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( Name.getTemplate() ); seqt.addElement( INTEGER.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); assert(seq.size() == 2); return new IssuerAndSerialNumber( (Name) seq.elementAt(0), (INTEGER) seq.elementAt(1) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs7/RecipientInfo.java000066400000000000000000000100101412550063600244260ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs7; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; public class RecipientInfo implements ASN1Value { public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } private INTEGER version; private IssuerAndSerialNumber issuerAndSerialNumber; private AlgorithmIdentifier keyEncryptionAlgorithmID; private OCTET_STRING encryptedKey; private SEQUENCE sequence = new SEQUENCE(); public INTEGER getVersion() { return version; } public IssuerAndSerialNumber getissuerAndSerialNumber() { return issuerAndSerialNumber; } public AlgorithmIdentifier getKeyEncryptionAlgorithmID() { return keyEncryptionAlgorithmID; } public OCTET_STRING getEncryptedKey() { return encryptedKey; } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * Create a RecipientInfo ASN1 object. */ public RecipientInfo( INTEGER version, IssuerAndSerialNumber issuerAndSerialNumber, AlgorithmIdentifier keyEncryptionAlgorithmID, OCTET_STRING encryptedKey) { assert(issuerAndSerialNumber != null); assert(keyEncryptionAlgorithmID != null); assert(encryptedKey != null); this.version = version; this.issuerAndSerialNumber = issuerAndSerialNumber; this.keyEncryptionAlgorithmID = keyEncryptionAlgorithmID; this.encryptedKey = encryptedKey; sequence.addElement(version); sequence.addElement(issuerAndSerialNumber); sequence.addElement(keyEncryptionAlgorithmID); sequence.addElement(encryptedKey); } @Override public void encode(OutputStream ostream) throws IOException { encode(getTag(),ostream); } @Override public void encode(Tag tag, OutputStream ostream) throws IOException { sequence.encode(tag,ostream); } /** * A template file for decoding a RecipientInfo blob * */ public static class Template implements ASN1Template { public Tag getTag() { return RecipientInfo.TAG; } @Override public boolean tagMatch(Tag tag) { return (tag.equals(RecipientInfo.TAG)); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(getTag(),istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { SEQUENCE.Template seqt = new SEQUENCE.Template(); seqt.addElement(new INTEGER.Template()); seqt.addElement(new IssuerAndSerialNumber.Template()); seqt.addElement(new AlgorithmIdentifier.Template()); seqt.addElement(new OCTET_STRING.Template()); SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); assert(seq.size() ==4); return new RecipientInfo( (INTEGER) seq.elementAt(0), (IssuerAndSerialNumber) seq.elementAt(1), (AlgorithmIdentifier) seq.elementAt(2), (OCTET_STRING) seq.elementAt(3) ); } } // end of template } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs7/SignedAndEnvelopedData.java000066400000000000000000000141611412550063600261730ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs7; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.SET; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; public class SignedAndEnvelopedData implements ASN1Value { /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private INTEGER version; private SET recipientInfos; private SET digestAlgorithms; private EncryptedContentInfo encryptedContentInfo; private SET certificates; // may be null private SET crls; // may be null private SET signerInfos; private SEQUENCE sequence; // for encoding /** * Returns the version number. The current version is 1. */ public INTEGER getVersion() { return version; } /** * Returns a SET of RecipientInfo. */ public SET getRecipientInfos() { return recipientInfos; } /** * Returns a SET of AlgorithmIdentifier. */ public SET getDigestAlgorithms() { return digestAlgorithms; } /** * Returns the encrypted content. */ public EncryptedContentInfo getEncryptedContentInfo() { return encryptedContentInfo; } /** * Returns a SET of ANYs. May return null if the * certificates field is not present. */ public SET getCertificates() { return certificates; } /** * Returns a SET of ANYs. May return null if the crls * field is not present. */ public SET getCrls() { return crls; } /** * Returns a SET of SignerInfo. */ public SET getSignerInfos() { return signerInfos; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// public SignedAndEnvelopedData( INTEGER version, SET recipientInfos, SET digestAlgorithms, EncryptedContentInfo encryptedContentInfo, SET certificates, SET crls, SET signerInfos) { if( version==null || recipientInfos==null || digestAlgorithms==null || encryptedContentInfo==null || signerInfos==null ) { throw new IllegalArgumentException( "SignedAndEnvelopedData constructor parameter is null"); } this.version = version; this.recipientInfos = recipientInfos; this.digestAlgorithms = digestAlgorithms; this.encryptedContentInfo = encryptedContentInfo; this.certificates = certificates; this.crls = crls; this.signerInfos = signerInfos; sequence = new SEQUENCE(); sequence.addElement(version); sequence.addElement(recipientInfos); sequence.addElement(digestAlgorithms); sequence.addElement(encryptedContentInfo); if( certificates!=null ) { sequence.addElement(certificates); } if( crls!=null ) { sequence.addElement(crls); } sequence.addElement( signerInfos ); } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } /** * A Template class for decoding BER-encoded SignedAndEnvelopedData items. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement(INTEGER.getTemplate()); seqt.addElement(new SET.OF_Template(RecipientInfo.getTemplate())); seqt.addElement(new SET.OF_Template( AlgorithmIdentifier.getTemplate()) ); seqt.addElement(EncryptedContentInfo.getTemplate()); seqt.addOptionalElement(new Tag(0), new SET.OF_Template(ANY.getTemplate())); seqt.addOptionalElement(new Tag(1), new SET.OF_Template(ANY.getTemplate())); seqt.addElement(new SET.OF_Template(SignerInfo.getTemplate())); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new SignedAndEnvelopedData( (INTEGER) seq.elementAt(0), (SET) seq.elementAt(1), (SET) seq.elementAt(2), (EncryptedContentInfo) seq.elementAt(3), (SET) seq.elementAt(4), (SET) seq.elementAt(5), (SET) seq.elementAt(6) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs7/SignedData.java000066400000000000000000000323361412550063600237120ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs7; import java.io.*; import org.mozilla.jss.asn1.*; import org.mozilla.jss.pkix.primitive.*; import org.mozilla.jss.pkix.cert.Certificate; /* CUT THIS??? *

Although all the normal functionality of a SignedData is supported * with high-level methods, there is a low-level API for setting the * individual fields of the structure. Using these calls is an unsupported * way of accomplishing unforeseen tasks. If you have reason to use these * methods, please notify the authors in case it is something that should * be added to the high-level interface. * */ /** * A PKCS #7 SignedData structure. This class implements version 1 * of the spec. *

The certificates field should only contain X.509 certificates. * PKCS #6 extended certificates will fail to decode properly. * @author stevep * @author nicolson */ public class SignedData implements ASN1Value { /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Members /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// private INTEGER version; private SET digestAlgorithms; private ContentInfo contentInfo; private SET certificates; // [0] optional, may be null private SET crls; // [1] optional, may be null private SET signerInfos; // This class implements version 1 of the spec. private static final INTEGER VERSION = new INTEGER(1); /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Accessor methods /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// private static void verifyNotNull(Object obj) { if( obj == null ) { throw new IllegalArgumentException(); } } /** * Returns the version of this SignedData. The current version of the * spec is version 1. */ public INTEGER getVersion() { return version; } /** * Low-level function to set the version. * @param version Must not be null. public void setVersion(INTEGER version) { verifyNotNull(version); this.version = version; } */ /** * Returns the digest algorithms used by the signers to digest the * signed content. There may be more than one, if different signers * use different digesting algorithms. */ public SET getDigestAlgorithmIdentifiers() { return digestAlgorithms; } /** * Low-level function to set the digest algorithm identifiers. * @param digestAlgIds Must not be null. public void setDigestAlgorithmIdentifiers(SET digestAlgIds) { verifyNotNull(digestAlgIds); this.digestAlgorithms = digestAlgIds; } */ /** * Returns the ContentInfo containing the signed content. The simple * case is for the content to be of type data, although any * content type can be signed. */ public ContentInfo getContentInfo() { return contentInfo; } /** * Low-level function to set the contentInfo. * @param ci Must not be null. public void setContentInfo(ContentInfo ci) { verifyNotNull(ci); this.contentInfo = ci; } */ /** * Returns the certificates field, which is a SET of * X.509 certificates (org.mozilla.jss.pkix.cert.Certificate). * PKCS #6 Extended Certificates are not supported by this implementation. * Returns null if this optional field is not present. * */ public SET getCertificates() { return certificates; } /** * Low-level function to set the certificates. * @param certs May be null to signify that the certificates * field is not present. public void setCertificates(SET certs) { this.certificates = certs; } */ /** * Returns true if the certificates field is present. */ public boolean hasCertificates() { return (certificates!=null); } /** * Returns the crls field, which contains a SET of certificate * revocation lists represented by ANYs (org.mozilla.jss.asn1.ANY). * */ public SET getCrls() { return crls; } /** * Low-level function to set the crls. * @param certs May be null to signify that the crls * field is not present. public void setCrls(SET crls) { this.crls = crls; } */ /** * Returns true if the crls field is present. */ public boolean hasCrls() { return (crls != null); } /** * Returns the signerInfos field, which is a SET of * org.mozilla.jss.pkcs7.SignerInfo. */ public SET getSignerInfos() { return signerInfos; } /** * Low-level function to set the SignerInfos. * @param signerInfos Must not be null. public void setSignerInfos(SET signerInfos) { verifyNotNull(sis); this.signerInfos = signerInfos; } */ /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// /** * Low-level constructor that merely initializes all fields to null. private SignedData() {} */ /** * Create a SignedData ASN1 object. Both certificates and CRLs * are optional. If you pass in a null for either value, that * parameter will not get written in the sequence. * * @param digestAlgorithms A SET of zero or more * algorithm identifiers. The purpose of this item is to list * the digest algorithms used by the various signers to digest * the signed content. This field will also be updated by * the addSigner method. If all the signers are added * with addSigner, it is not necessary to list * the digest algorithms here. *

If null is passed in, the * digestAlgorithms field will be initialized * with an empty SET. * @param contentInfo The content that is being signed. This parameter * may not be null. However, the content * field of the contentInfo may be omitted, in which case the * signatures contained in the SignerInfo structures * are presumed to be on externally-supplied data. * @param certificates A SET of org.mozilla.jss.pkix.cert.Certificate, * the certificates * containing the public keys used to sign the content. It may * also contain elements of the CA chain extending from the leaf * certificates. It is not necessary to include the CA chain, or * indeed to include any certificates, if the certificates are * expected to already be possessed by the recipient. The recipient * can use the issuer and serial number in the SignerInfo structure * to search for the necessary certificates. If this parameter is * null, the certificates field will be * omitted. * @param crls A SET of ASN1Values, which should encode to the ASN1 type * CertificateRevocationList. This implementation does * not interpret CRLs. If this parameter is null, * the crls field will be omitted. * @param signerInfos SignerInfo structures containing signatures * of the content. Additional signerInfos can be added with * the addSigner method. If this parameter is * null, the field will be initialized with an * empty SET. */ public SignedData( SET digestAlgorithms, ContentInfo contentInfo, SET certificates, SET crls, SET signerInfos) { version = VERSION; if(digestAlgorithms == null ) { this.digestAlgorithms = new SET(); } else { this.digestAlgorithms = digestAlgorithms; } verifyNotNull(contentInfo); this.contentInfo = contentInfo; // certificates may be null this.certificates = certificates; // crls may be null this.crls = crls; if(signerInfos == null) { this.signerInfos = new SET(); } else { this.signerInfos = signerInfos; } } /** * Constructor for creating a SignedData from its encoding. */ SignedData( INTEGER version, SET digestAlgorithms, ContentInfo contentInfo, SET certificates, SET crls, SET signerInfos ) { verifyNotNull(version); this.version = version; verifyNotNull(digestAlgorithms); this.digestAlgorithms = digestAlgorithms; verifyNotNull(contentInfo); this.contentInfo = contentInfo; // certificates may be null this.certificates = certificates; // crls may be null this.crls = crls; verifyNotNull(signerInfos); this.signerInfos = signerInfos; } /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Cryptographic functions /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(getTag(),ostream); } @Override public void encode(Tag tag, OutputStream ostream) throws IOException { SEQUENCE sequence = new SEQUENCE(); sequence.addElement(version); sequence.addElement(digestAlgorithms); sequence.addElement(contentInfo); if( certificates != null ) { sequence.addElement( new Tag(0), certificates ); } if( crls != null ) { sequence.addElement( new Tag(1), crls ); } sequence.addElement(signerInfos); sequence.encode(tag,ostream); } /** * A template file for decoding a SignedData blob * */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); // version seqt.addElement(INTEGER.getTemplate()); // digestAlgorithms seqt.addElement(new SET.OF_Template( AlgorithmIdentifier.getTemplate())); // content info seqt.addElement(ContentInfo.getTemplate()); // [0] IMPLICIT certificates OPTIONAL seqt.addOptionalElement( new Tag(0), new SET.OF_Template(Certificate.getTemplate())); // [1] IMPLICIT CertificateRevocationLists OPTIONAL seqt.addOptionalElement( new Tag(1), new SET.OF_Template(ANY.getTemplate())); // signerInfos seqt.addElement(new SET.OF_Template(SignerInfo.getTemplate())); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); assert(seq.size() == 6); return new SignedData( (INTEGER) seq.elementAt(0), (SET) seq.elementAt(1), (ContentInfo) seq.elementAt(2), (SET) seq.elementAt(3), (SET) seq.elementAt(4), (SET) seq.elementAt(5) ); } } // end of template } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs7/SignerInfo.java000066400000000000000000000755541412550063600237630ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkcs7; import java.io.*; import org.mozilla.jss.asn1.*; import org.mozilla.jss.pkix.primitive.*; import org.mozilla.jss.crypto.*; import java.security.InvalidKeyException; import java.security.SignatureException; import java.security.NoSuchAlgorithmException; import java.security.MessageDigest; import org.mozilla.jss.*; import java.security.PublicKey; /* * The high-level interface takes care of all * the logic and cryptography. If you need to use the low-level interface, * please let us know what you are using it for. Perhaps it should be part * of the high-level interface. */ /** * A PKCS #7 SignerInfo. */ public class SignerInfo implements ASN1Value { //////////////////////////////////////////////// // PKCS #9 attributes //////////////////////////////////////////////// private static final OBJECT_IDENTIFIER CONTENT_TYPE = OBJECT_IDENTIFIER.PKCS.subBranch(9).subBranch(3); private static final OBJECT_IDENTIFIER MESSAGE_DIGEST = OBJECT_IDENTIFIER.PKCS.subBranch(9).subBranch(4); /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Members /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// private INTEGER version; private IssuerAndSerialNumber issuerAndSerialNumber; private AlgorithmIdentifier digestAlgorithm; private SET authenticatedAttributes; // [0] OPTIONAL private AlgorithmIdentifier digestEncryptionAlgorithm; private OCTET_STRING encryptedDigest; private SET unauthenticatedAttributes; // [1] OPTIONAL // we only do version 1 of PKCS #7 private static final INTEGER VERSION = new INTEGER(1); /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Accessor methods /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// /** * Retrieves the version number of this SignerInfo. */ public INTEGER getVersion() { return version; } /** * Low-level method to set the version. * It is not normally necessary to call this. Use it at your own risk. public void setVersion(INTEGER version) { this.version = version; } */ /** * Retrieves the issuer and serial number of the certificate whose * private key was used to sign the SignerInfo. */ public IssuerAndSerialNumber getIssuerAndSerialNumber() { return issuerAndSerialNumber; } /** * Low-level method to set the issuerAndSerialNumber. * It is not normally necessary to call this. Use it at your own risk. public void setIssuerAndSerialNumber( IssuerAndSerialNumber iasn ) { this.issuerAndSerialNumber = iasn; } */ /** * Retrieves the DigestAlgorithm used in this SignerInfo. * * @exception NoSuchAlgorithmException If the algorithm is not recognized * by JSS. */ public DigestAlgorithm getDigestAlgorithm() throws NoSuchAlgorithmException { return DigestAlgorithm.fromOID( digestAlgorithm.getOID() ); } /** * Retrieves the DigestAlgorithmIdentifier used in this SignerInfo. */ public AlgorithmIdentifier getDigestAlgorithmIdentifer() { return digestAlgorithm; } /** * Low-level method to set the digest AlgorithmIdentifier. * It is not normally necessary to call this. Use it at your own risk. public void setDigestAlgorithmIdentifier(AlgorithmIdentifier algid) { this.digestAlgorithm = algid; } */ /** * Retrieves the authenticated attributes, if they exist. * */ public SET getAuthenticatedAttributes() { return authenticatedAttributes; } /** * Returns true if the authenticatedAttributes field is present. */ public boolean hasAuthenticatedAttributes() { return (authenticatedAttributes != null); } /** * Low-level method to set the authenticatedAttributes field. * It is not normally necessary to call this. Use it at your own risk. public void setAuthenticatedAttributes(SET authAttrib) { this.authenticatedAttributes = authAttrib; } */ /** * Returns the raw signature (digest encryption) algorithm used in this * SignerInfo. * * @exception NoSuchAlgorithmException If the algorithm is not recognized * by JSS. */ public SignatureAlgorithm getDigestEncryptionAlgorithm() throws NoSuchAlgorithmException { return SignatureAlgorithm.fromOID( digestEncryptionAlgorithm.getOID() ); } /** * Returns the DigestEncryptionAlgorithmIdentifier used in this SignerInfo. */ public AlgorithmIdentifier getDigestEncryptionAlgorithmIdentifier() { return digestEncryptionAlgorithm; } /** * Low-level method to set the digestEncryptionAlgorithm field. * It is not normally necessary to call this. Use it at your own risk. public void setDigestEncryptionAlgorithmIdentifier(AlgorithmIdentifier algid) { this.digestEncryptionAlgorithm= algid; } */ /** * Retrieves the encrypted digest. */ public byte[] getEncryptedDigest() { return encryptedDigest.toByteArray(); } /** * Low-level method to set the encryptedDigest field. * It is not normally necessary to call this. Use it at your own risk. public void setEncryptedDigest(byte[] ed) { this.encryptedDigest = new OCTET_STRING(ed); } */ /** * Retrieves the unauthenticated attributes, if they exist. * */ public SET getUnauthenticatedAttributes() { return unauthenticatedAttributes; } /** * Returns true if the unauthenticatedAttributes field is present. */ public boolean hasUnauthenticatedAttributes() { return (unauthenticatedAttributes!=null); } /** * Low-level method to set the unauthenticatedAttributes field. * It is not normally necessary to call this. Use it at your own risk. public void setUnauthenticatedAttributes(SET unauthAttrib) { this.unauthenticatedAttributes = unauthAttrib; } */ /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// /** * Low-level default constructor. All fields are initialized to null. * Before this SignerInfo can be processed or used in any way, all of * the fields except authenticatedAttributes and * unauthenticatedAttributes must be non-null. *

It is not normally necessary to call this constructor.Use it at * your own risk. public SignerInfo() { } */ /** * A constructor for creating a new SignerInfo from scratch. * * @param issuerAndSerialNumber The issuer and serial number of the * certificate from which the public key was extracted to create * this SignerInfo. * @param signingAlg The algorithm to be used to sign the content. * This should be a composite algorithm, such as * RSASignatureWithMD5Digest, instead of a raw algorithm, such as * RSASignature. * Note that the digest portion of this algorithm must be the same * algorithm as was used to digest the message content. * @param authenticatedAttributes An optional set of Attributes, which * will be signed along with the message content. This parameter may * be null, or the SET may be empty. DO NOT insert * the PKCS #9 content-type or message-digest attributes. They will * be added automatically if they are necessary. * @param unauthenticatedAttributes An optional set of Attributes, which * will be included in the SignerInfo but not signed. This parameter * may be null, or the SET may be empty. * @param messageDigest The digest of the message contents. The digest * must have been created with the digest algorithm specified by * the signingAlg parameter. * @param contentType The type of the ContentInfo that is being signed. * If it is not data, then the PKCS #9 attributes * content-type and message-digest will be automatically computed and * added to the authenticated attributes. */ public SignerInfo( IssuerAndSerialNumber issuerAndSerialNumber, SET authenticatedAttributes, SET unauthenticatedAttributes, OBJECT_IDENTIFIER contentType, byte[] messageDigest, SignatureAlgorithm signingAlg, PrivateKey signingKey ) throws InvalidKeyException, NoSuchAlgorithmException, NotInitializedException, SignatureException, TokenException { version = VERSION; this.issuerAndSerialNumber = issuerAndSerialNumber; this.digestAlgorithm = new AlgorithmIdentifier(signingAlg.getDigestAlg().toOID(),null); // if content-type is not data, add message-digest and content-type // to authenticated attributes. if( ! contentType.equals(ContentInfo.DATA) ) { if( authenticatedAttributes == null ) { authenticatedAttributes = new SET(); } Attribute attrib = new Attribute(CONTENT_TYPE, ContentInfo.DATA); authenticatedAttributes.addElement(attrib); attrib = new Attribute(MESSAGE_DIGEST, new OCTET_STRING(messageDigest) ); authenticatedAttributes.addElement(attrib); } digestEncryptionAlgorithm = new AlgorithmIdentifier( signingAlg.getRawAlg().toOID(),null ); if( authenticatedAttributes != null ) { assert( authenticatedAttributes.size() >= 2 ); this.authenticatedAttributes = authenticatedAttributes; } ////////////////////////////////////////////////// // create encrypted digest (signature) ////////////////////////////////////////////////// // compute the digest byte[] digest=null; DigestAlgorithm digestAlg = signingAlg.getDigestAlg(); if( authenticatedAttributes == null ) { // just use the message digest of the content digest = messageDigest; } else { // digest the contents octets of the authenticated attributes byte[] enc = ASN1Util.encode(authenticatedAttributes); MessageDigest md = MessageDigest.getInstance(digestAlg.toString()); digest = md.digest( enc ); } byte[] toBeSigned; if( signingAlg.getRawAlg() == SignatureAlgorithm.RSASignature ) { // put the digest in a DigestInfo SEQUENCE digestInfo = new SEQUENCE(); AlgorithmIdentifier digestAlgId = new AlgorithmIdentifier( digestAlg.toOID(),null ); digestInfo.addElement( digestAlgId ); digestInfo.addElement( new OCTET_STRING( digest ) ); toBeSigned = ASN1Util.encode(digestInfo); } else { toBeSigned = digest; } // encrypt the DER-encoded DigestInfo with the private key CryptoToken token = signingKey.getOwningToken(); Signature sig; sig = token.getSignatureContext( signingAlg.getRawAlg() ); sig.initSign(signingKey); sig.update(toBeSigned); encryptedDigest = new OCTET_STRING(sig.sign()); if( unauthenticatedAttributes != null ) { this.unauthenticatedAttributes = unauthenticatedAttributes; } } /** * A constructor for creating a new SignerInfo from its decoding. */ SignerInfo( INTEGER version, IssuerAndSerialNumber issuerAndSerialNumber, AlgorithmIdentifier digestAlgorithm, SET authenticatedAttributes, AlgorithmIdentifier digestEncryptionAlgorithm, byte[] encryptedDigest, SET unauthenticatedAttributes) { this.version = version; this.issuerAndSerialNumber = issuerAndSerialNumber; this.digestAlgorithm = digestAlgorithm; this.authenticatedAttributes = authenticatedAttributes; this.digestEncryptionAlgorithm = digestEncryptionAlgorithm; this.encryptedDigest = new OCTET_STRING(encryptedDigest); this.unauthenticatedAttributes = unauthenticatedAttributes; } /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Verification /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// /** * Verifies that this SignerInfo contains a valid signature of the * given message digest. If any authenticated attributes are present, * they are also validated. The verification algorithm is as follows: * Note that this does not verify the validity of the * the certificate itself, only the signature.

    * *
  • If no authenticated attributes are present, the content type is * verified to be data. Then it is verified that the message * digest passed * in, when encrypted with the given public key, matches the encrypted * digest in the SignerInfo. * *
  • If authenticated attributes are present, * two particular attributes must be present:
      *
    • PKCS #9 Content-Type, the type of content that is being signed. * This must match the contentType parameter. *
    • PKCS #9 Message-Digest, the digest of the content that is being * signed. This must match the messageDigest parameter. *
    * After these two attributes are verified to be both present and correct, * the encryptedDigest field of the SignerInfo is verified to be the * signature of the contents octets of the DER encoding of the * authenticatedAttributes field. * *
* * @param messageDigest The hash of the content that is signed by this * SignerInfo. * @param contentType The type of the content that is signed by this * SignerInfo. * @exception ObjectNotFoundException If no certificate matching the * the issuer name and serial number can be found. */ public void verify(byte[] messageDigest, OBJECT_IDENTIFIER contentType) throws NotInitializedException, NoSuchAlgorithmException, InvalidKeyException, TokenException, SignatureException, ObjectNotFoundException { CryptoManager cm = CryptoManager.getInstance(); X509Certificate cert = cm.findCertByIssuerAndSerialNumber( ASN1Util.encode(issuerAndSerialNumber.getIssuer()), issuerAndSerialNumber.getSerialNumber() ); verify(messageDigest, contentType, cert.getPublicKey()); } /** * Verifies that this SignerInfo contains a valid signature of the * given message digest. If any authenticated attributes are present, * they are also validated. The verification algorithm is as follows:
    * *
  • If no authenticated attributes are present, the content type is * verified to be data. Then it is verified that the message * digest passed * in, when encrypted with the given public key, matches the encrypted * digest in the SignerInfo. * *
  • If authenticated attributes are present, * two particular attributes must be present:
      *
    • PKCS #9 Content-Type, the type of content that is being signed. * This must match the contentType parameter. *
    • PKCS #9 Message-Digest, the digest of the content that is being * signed. This must match the messageDigest parameter. *
    * After these two attributes are verified to be both present and correct, * the encryptedDigest field of the SignerInfo is verified to be the * signature of the contents octets of the DER encoding of the * authenticatedAttributes field. * *
* * @param messageDigest The hash of the content that is signed by this * SignerInfo. * @param contentType The type of the content that is signed by this * SignerInfo. * @param pubkey The public key to use to verify the signature. */ public void verify(byte[] messageDigest, OBJECT_IDENTIFIER contentType, PublicKey pubkey) throws NotInitializedException, NoSuchAlgorithmException, InvalidKeyException, TokenException, SignatureException { if( authenticatedAttributes == null ) { verifyWithoutAuthenticatedAttributes(messageDigest, contentType, pubkey); } else { verifyWithAuthenticatedAttributes(messageDigest, contentType, pubkey); } } /** * Verifies that the message digest passed in, when encrypted with the * given public key, matches the encrypted digest in the SignerInfo. */ private void verifyWithoutAuthenticatedAttributes (byte[] messageDigest, OBJECT_IDENTIFIER contentType, PublicKey pubkey) throws NotInitializedException, NoSuchAlgorithmException, InvalidKeyException, TokenException, SignatureException { if( ! contentType.equals(ContentInfo.DATA) ) { // only data can be signed this way. Everything else has // to go into authenticatedAttributes. throw new SignatureException( "Content-Type is not DATA, but there are"+ " no authenticated attributes"); } SignatureAlgorithm sigAlg = SignatureAlgorithm.fromOID( digestEncryptionAlgorithm.getOID() ); byte[] toBeVerified; if( sigAlg.getRawAlg() == SignatureAlgorithm.RSASignature ) { // create DigestInfo structure SEQUENCE digestInfo = new SEQUENCE(); digestInfo.addElement( new AlgorithmIdentifier(digestAlgorithm.getOID(), null) ); digestInfo.addElement( new OCTET_STRING(messageDigest) ); toBeVerified = ASN1Util.encode(digestInfo); } else { toBeVerified = messageDigest; } CryptoToken token = CryptoManager.getInstance() .getInternalCryptoToken(); Signature sig = token.getSignatureContext(sigAlg); sig.initVerify(pubkey); sig.update(toBeVerified); if( sig.verify(encryptedDigest.toByteArray()) ) { return; // success } else { throw new SignatureException( "Encrypted message digest parameter does not "+ "match encrypted digest in SignerInfo"); } } /** * Verifies a SignerInfo with authenticated attributes. If authenticated * attributes are present, then two particular attributes must * be present:
    *
  • PKCS #9 Content-Type, the type of content that is being signed. * This must match the contentType parameter. *
  • PKCS #9 Message-Digest, the digest of the content that is being * signed. This must match the messageDigest parameter. *
* After these two attributes are verified to be both present and correct, * the encryptedDigest field of the SignerInfo is verified to be the * signature of the contents octets of the DER encoding of the * authenticatedAttributes field. */ private void verifyWithAuthenticatedAttributes (byte[] messageDigest, OBJECT_IDENTIFIER contentType, PublicKey pubkey) throws NotInitializedException, NoSuchAlgorithmException, InvalidKeyException, TokenException, SignatureException { int numAttrib = authenticatedAttributes.size(); if(numAttrib < 2) { throw new SignatureException( "At least two authenticated attributes must be present:"+ " content-type and message-digest"); } // go through the authenticated attributes, verifying the // interesting ones boolean foundContentType = false; boolean foundMessageDigest = false; for( int i = 0; i < numAttrib; i++ ) { if( ! (authenticatedAttributes.elementAt(i) instanceof Attribute)) { throw new SignatureException( "Element of authenticatedAttributes is not an Attribute"); } Attribute attrib = (Attribute) authenticatedAttributes.elementAt(i); if( attrib.getType().equals(CONTENT_TYPE) ) { // content-type. Compare with what was passed in. SET vals = attrib.getValues(); if( vals.size() != 1 ) { throw new SignatureException( "Content-Type attribute "+ " does not have exactly one value"); } ASN1Value val = vals.elementAt(0); OBJECT_IDENTIFIER ctype; try { if( val instanceof OBJECT_IDENTIFIER ) { ctype = (OBJECT_IDENTIFIER) val; } else if( val instanceof ANY ) { ctype = (OBJECT_IDENTIFIER) ((ANY)val).decodeWith( OBJECT_IDENTIFIER.getTemplate() ); } else { // what the heck is it? not what it's supposed to be throw new InvalidBERException( "Content-Type authenticated attribute has unexpected"+ " content type"); } } catch( InvalidBERException e ) { throw new SignatureException( "Content-Type authenticated attribute does not have "+ "OBJECT IDENTIFIER value"); } // compare the content type in the attribute to the // contentType parameter if( ! ctype.equals( contentType ) ) { throw new SignatureException( "Content-type in authenticated attributes does not "+ "match content-type being verified"); } // content type is A-OK foundContentType = true; } else if( attrib.getType().equals(MESSAGE_DIGEST) ) { SET vals = attrib.getValues(); if( vals.size() != 1 ) { throw new SignatureException( "Message-digest attribute does not have"+ " exactly one value"); } ASN1Value val = vals.elementAt(0); byte[] mdigest; try { if( val instanceof OCTET_STRING ) { mdigest = ((OCTET_STRING)val).toByteArray(); } else if( val instanceof ANY ) { OCTET_STRING os; os = (OCTET_STRING) ((ANY)val).decodeWith( OCTET_STRING.getTemplate() ); mdigest = os.toByteArray(); } else { // what the heck is it? not what it's supposed to be throw new InvalidBERException( "Content-Type authenticated attribute has unexpected"+ " content type"); } } catch( InvalidBERException e ) { throw new SignatureException( "Message-digest attribute does not"+ " have OCTET STRING value"); } // compare the message digest in the attribute to the // message digest being verified if( ! byteArraysAreSame(mdigest, messageDigest) ) { throw new SignatureException( "Message-digest attribute does not"+ " match message digest being verified"); } // message digest is A-OK foundMessageDigest = true; } // we don't care about other attributes } if( !foundContentType ) { throw new SignatureException( "Authenticated attributes does not contain"+ " PKCS #9 content-type attribute"); } if( !foundMessageDigest ) { throw new SignatureException( "Authenticate attributes does not contain"+ " PKCS #9 message-digest attribute"); } SignatureAlgorithm sigAlg = SignatureAlgorithm.fromOID(digestEncryptionAlgorithm.getOID()); // All the authenticated attributes are present and correct. // Now verify the signature. CryptoToken token = CryptoManager.getInstance().getInternalCryptoToken(); Signature sig = token.getSignatureContext( sigAlg ); sig.initVerify(pubkey); // verify the contents octets of the DER encoded authenticated attribs byte[] toBeDigested; toBeDigested = ASN1Util.encode(authenticatedAttributes); MessageDigest md = MessageDigest.getInstance( DigestAlgorithm.fromOID(digestAlgorithm.getOID()).toString() ); byte[] digest = md.digest(toBeDigested); byte[] toBeVerified; if( sigAlg.getRawAlg() == SignatureAlgorithm.RSASignature ) { // create DigestInfo structure SEQUENCE digestInfo = new SEQUENCE(); digestInfo.addElement( new AlgorithmIdentifier(digestAlgorithm.getOID(),null) ); digestInfo.addElement( new OCTET_STRING(digest) ); toBeVerified = ASN1Util.encode(digestInfo); } else { toBeVerified = digest; } sig.update( toBeVerified ); if( ! sig.verify(encryptedDigest.toByteArray()) ) { // signature is invalid throw new SignatureException("encryptedDigest was not the correct"+ " signature of the contents octets of the DER-encoded"+ " authenticated attributes"); } // SUCCESSFULLY VERIFIED } /** * Compares two non-null byte arrays. Returns true if they are identical, * false otherwise. */ private static boolean byteArraysAreSame(byte[] left, byte[] right) { assert(left!=null && right!=null); if( left.length != right.length ) { return false; } for(int i = 0 ; i < left.length ; i++ ) { if( left[i] != right[i] ) { return false; } } return true; } /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // DER-encoding /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(getTag(),ostream); } @Override public void encode(Tag tag, OutputStream ostream) throws IOException { SEQUENCE sequence = new SEQUENCE(); sequence.addElement( version ); sequence.addElement( issuerAndSerialNumber ); sequence.addElement( digestAlgorithm ); if( authenticatedAttributes != null ) { sequence.addElement( new Tag(0), authenticatedAttributes ); } sequence.addElement( digestEncryptionAlgorithm ); sequence.addElement( encryptedDigest ); if( unauthenticatedAttributes != null ) { sequence.addElement( new Tag(1), unauthenticatedAttributes ); } sequence.encode(tag,ostream); } public static Template getTemplate() { return templateInstance; } private static Template templateInstance = new Template(); /** * A template for decoding a SignerInfo blob * */ public static class Template implements ASN1Template { SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); // serial number seqt.addElement(INTEGER.getTemplate()); // vn // issuerAndSerialNumber seqt.addElement(IssuerAndSerialNumber.getTemplate()); // issuer + sernum // digestAlgorithm seqt.addElement(AlgorithmIdentifier.getTemplate()); // digest alg // authenticatedAttributes seqt.addOptionalElement( new Tag(0), new SET.OF_Template(Attribute.getTemplate())); // digestEncryptionAlgorithm seqt.addElement(AlgorithmIdentifier.getTemplate()); // dig encr alg // encryptedDigest seqt.addElement(OCTET_STRING.getTemplate()); // encr digest // unauthenticated attributes seqt.addOptionalElement( new Tag(1), new SET.OF_Template(Attribute.getTemplate())); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG,istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); assert(seq.size() == 7); return new SignerInfo( (INTEGER) seq.elementAt(0), (IssuerAndSerialNumber) seq.elementAt(1), (AlgorithmIdentifier) seq.elementAt(2), (SET) seq.elementAt(3), (AlgorithmIdentifier) seq.elementAt(4), ((OCTET_STRING) seq.elementAt(5)).toByteArray(), (SET) seq.elementAt(6) ); } } // end of template } jss-5.0.0/src/main/java/org/mozilla/jss/pkcs7/package.html000066400000000000000000000004321412550063600233150ustar00rootroot00000000000000 Creating and interpeting PKCS #7 blobs. jss-5.0.0/src/main/java/org/mozilla/jss/pkix/000077500000000000000000000000001412550063600207615ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cert/000077500000000000000000000000001412550063600217165ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cert/Certificate.java000066400000000000000000000303241412550063600250050ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cert; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.InvalidKeyException; import java.security.KeyPair; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.SignatureException; import java.security.cert.CertificateException; import java.util.Calendar; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BIT_STRING; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.InvalidKeyFormatException; import org.mozilla.jss.crypto.KeyPairAlgorithm; import org.mozilla.jss.crypto.KeyPairGenerator; import org.mozilla.jss.crypto.PrivateKey; import org.mozilla.jss.crypto.Signature; import org.mozilla.jss.crypto.SignatureAlgorithm; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; import org.mozilla.jss.pkix.primitive.Name; /** * An X.509 signed certificate. */ public class Certificate implements ASN1Value { private CertificateInfo info; private byte[] infoEncoding; private byte[] signature; private AlgorithmIdentifier algId; SEQUENCE sequence; Certificate(CertificateInfo info, byte[] infoEncoding, AlgorithmIdentifier algId, byte[] signature) throws IOException { this.info = info; this.infoEncoding = infoEncoding; this.algId = algId; this.signature = signature; // bundle everything into a SEQUENCE sequence = new SEQUENCE(); sequence.addElement( info ); sequence.addElement( algId ); sequence.addElement( new BIT_STRING( signature, 0 ) ); } /** * Creates and signs an X.509 Certificate. * @param info A CertificateInfo (TBSCertificate), which specifies * the actual information of the certificate. * @param privKey The private key with which to sign the certificate. * @param signingAlg The algorithm to use to sign the certificate. * It must match the algorithm specified in the CertificateInfo. * @exception IOException If an error occurred while encoding the * certificate. * @exception NotInitializedException Because this * operation involves cryptography (signing), CryptoManager must * be initialized before calling it. * @exception TokenException If an error occurs on a PKCS #11 token. * @exception NoSuchAlgorithmException If the OID for the signing algorithm * cannot be located. * @exception CertificateException If the signing algorithm specified * as a parameter does not match the one in the certificate info. * @exception InvalidKeyException If the key does not match the signing * algorithm. * @exception SignatureException If an error occurs while signing the * certificate. */ public Certificate(CertificateInfo info, java.security.PrivateKey privKey, SignatureAlgorithm signingAlg) throws IOException, NotInitializedException, TokenException, NoSuchAlgorithmException, CertificateException, InvalidKeyException, SignatureException { // make sure key is a Ninja private key if( !(privKey instanceof PrivateKey) ) { throw new InvalidKeyException("Private Key is does not belong to"+ " this provider"); } PrivateKey priv = (PrivateKey)privKey; // create algId and compare to the one in the cert info if(signingAlg.getSigningAlg() == SignatureAlgorithm.RSASignature) { algId = new AlgorithmIdentifier( signingAlg.toOID(), null ); } else { algId = new AlgorithmIdentifier( signingAlg.toOID() ); } if( ! info.getSignatureAlgId().getOID().equals(algId.getOID()) ) { throw new CertificateException("Signing Algorithm does not match"+ " the one specified in the CertificateInfo"); } // encode the cert info this.info = info; infoEncoding = ASN1Util.encode(info); // sign the info encoding CryptoManager cm = CryptoManager.getInstance(); CryptoToken token = priv.getOwningToken(); Signature sig = token.getSignatureContext(signingAlg); sig.initSign(priv); sig.update(infoEncoding); signature = sig.sign(); // bundle everything into a SEQUENCE sequence = new SEQUENCE(); sequence.addElement( info ); sequence.addElement( algId ); sequence.addElement( new BIT_STRING( signature, 0 ) ); } /** * Verifies the signature on this certificate. Does not indicate * that the certificate is valid at any specific time. */ public void verify() throws InvalidKeyException, NotInitializedException, NoSuchAlgorithmException, CertificateException, SignatureException, InvalidKeyFormatException { verify( info.getSubjectPublicKeyInfo().toPublicKey() ); } /** * Verifies the signature on this certificate, using the given public key. * Does not indicate the certificate is valid at any specific time. */ public void verify(PublicKey key) throws InvalidKeyException, NoSuchAlgorithmException, CertificateException, SignatureException { try { CryptoManager cm = CryptoManager.getInstance(); verify(key, cm.getInternalCryptoToken()); } catch( NotInitializedException e ) { throw new SignatureException("CryptoManager not initialized"); } } /** * Verifies the signature on this certificate, using the given public * key and CryptoToken. Does not indicate the certificate is valid at * any specific time. */ public void verify(PublicKey key, CryptoToken token) throws NoSuchAlgorithmException, CertificateException, SignatureException, InvalidKeyException { try { Signature sig = token.getSignatureContext( SignatureAlgorithm.fromOID( info.getSignatureAlgId().getOID() ) ); sig.initVerify(key); sig.update(infoEncoding); if( ! sig.verify(signature) ) { throw new CertificateException("Signature is invalid"); } } catch(TokenException e) { throw new SignatureException("PKCS #11 token error: " + e.getMessage()); } } /** * Returns the information (TBSCertificate) contained in this certificate. */ public CertificateInfo getInfo() { return info; } private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); //seqt.addElement( CertificateInfo.getTemplate() ); seqt.addElement( new ANY.Template() ); seqt.addElement( AlgorithmIdentifier.getTemplate() ); seqt.addElement( BIT_STRING.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); ANY infoAny = (ANY)seq.elementAt(0); byte[] infoEncoding = infoAny.getEncoded(); CertificateInfo info = (CertificateInfo) infoAny.decodeWith( CertificateInfo.getTemplate() ); // although signature is a bit string, all algorithms we use // will produce an octet string. BIT_STRING bs = (BIT_STRING) seq.elementAt(2); if( bs.getPadCount() != 0 ) { throw new InvalidBERException("signature does not fall into"+ " an integral number of bytes"); } byte[] signature = bs.getBits(); return new Certificate( info, infoEncoding, (AlgorithmIdentifier) seq.elementAt(1), signature ); } } public static void main(String argv[]) { try { if(argv.length > 2 || argv.length < 1) { System.out.println("Usage: Certificate []"); System.exit(0); } CryptoManager.initialize( argv[0] ); CryptoManager cm = CryptoManager.getInstance(); Certificate cert; // read in a cert FileInputStream fis = new FileInputStream(argv[1]); try (BufferedInputStream bis = new BufferedInputStream(fis)) { cert = (Certificate) Certificate.getTemplate().decode(bis); } CertificateInfo info = cert.getInfo(); info.print(System.out); //X509Certificate hardcore = cm.findCertByNickname("Hardcore"); //PublicKey key = hardcore.getPublicKey(); cert.verify(); System.out.println("verified"); FileOutputStream fos = new FileOutputStream("certinfo.der"); info.encode(fos); fos.close(); // make a new public key CryptoToken token = cm.getInternalKeyStorageToken(); KeyPairGenerator kpg = token.getKeyPairGenerator(KeyPairAlgorithm.RSA); kpg.initialize(512); System.out.println("Generating a new key pair..."); KeyPair kp = kpg.genKeyPair(); System.out.println("Generated key pair"); // set the certificate's public key info.setSubjectPublicKeyInfo(kp.getPublic()); // increment serial number int newSerial = info.getSerialNumber().intValue() + 1; info.setSerialNumber( new INTEGER(newSerial) ); // make new Name Name name = new Name(); name.addCommonName("Stra\u00dfenverk\u00e4ufer 'R' Us"); name.addCountryName("US"); name.addOrganizationName("Some Corporation"); name.addOrganizationalUnitName("some org unit?"); name.addLocalityName("Silicon Valley"); name.addStateOrProvinceName("California"); info.setIssuer(name); info.setSubject(name); // set validity Calendar cal = Calendar.getInstance(); cal.set(1997, Calendar.APRIL, 1); info.setNotBefore( cal.getTime() ); cal.set(2010, Calendar.APRIL, 1); info.setNotAfter( cal.getTime() ); System.out.println("About to create a new cert..."); // create a new cert from this certinfo Certificate genCert = new Certificate(info, kp.getPrivate(), SignatureAlgorithm.RSASignatureWithMD5Digest); System.out.println("Created new cert"); genCert.verify(); System.out.println("Cert verifies!"); fos = new FileOutputStream("gencert.der"); genCert.encode(fos); fos.close(); } catch( Exception e ) { e.printStackTrace(); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cert/CertificateInfo.java000066400000000000000000000403011412550063600256150ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cert; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.security.PublicKey; import java.security.cert.CertificateException; import java.util.Calendar; import java.util.Date; import java.util.TimeZone; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BIT_STRING; import org.mozilla.jss.asn1.CHOICE; import org.mozilla.jss.asn1.EXPLICIT; import org.mozilla.jss.asn1.GeneralizedTime; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.asn1.TimeBase; import org.mozilla.jss.asn1.UTCTime; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; import org.mozilla.jss.pkix.primitive.Name; import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo; /** * A TBSCertificate (to-be-signed certificate), the actual information in * a certificate apart from the signature. */ public class CertificateInfo implements ASN1Value { /** * An X.509 Certificate version. */ public static class Version { private Version() { } private Version(int vers, String string) { versionNumber = vers; this.string = string; } int versionNumber; String string; @Override public boolean equals(Object obj) { if(obj == null || !(obj instanceof Version)) { return false; } return ((Version)obj).versionNumber == versionNumber; } public int getNumber() { return versionNumber; } /** * Creates a version number from its numeric encoding. */ public static Version fromInt(int versionNum) throws InvalidBERException { if( versionNum == 0 ) { return v1; } else if( versionNum == 1) { return v2; } else if( versionNum == 2) { return v3; } else { throw new InvalidBERException("Unrecognized version number"); } } @Override public String toString() { return string; } public static final Version v1 = new Version(0, "v1"); public static final Version v2 = new Version(1, "v2"); public static final Version v3 = new Version(2, "v3"); } public static final Version v1 = Version.v1; public static final Version v2 = Version.v2; public static final Version v3 = Version.v3; // the last year for using UTCTime static final int UTCTIME_CUTOFF_YEAR = 2049; private Version version = v1; private INTEGER serialNumber; private AlgorithmIdentifier signatureAlgId; private Name issuer; private Date notBefore; private Date notAfter; private Name subject; private SubjectPublicKeyInfo subjectPublicKeyInfo; private BIT_STRING issuerUniqueIdentifier; // may be null private BIT_STRING subjectUniqueIdentifier; // may be null private SEQUENCE extensions; // if no extensions, size() == 0. Never null. /** * Creates a CertificateInfo with the required fields. */ public CertificateInfo(Version version, INTEGER serialNumber, AlgorithmIdentifier signatureAlgId, Name issuer, Date notBefore, Date notAfter, Name subject, SubjectPublicKeyInfo subjectPublicKeyInfo) { setVersion(version); setSerialNumber(serialNumber); setSignatureAlgId(signatureAlgId); setIssuer(issuer); setNotBefore(notBefore); setNotAfter(notAfter); setSubject(subject); setSubjectPublicKeyInfo(subjectPublicKeyInfo); extensions = new SEQUENCE(); } public void setVersion(Version version) { verifyNotNull(version); this.version = version; } public Version getVersion() { return version; } public void setSerialNumber(INTEGER serialNumber) { verifyNotNull(serialNumber); this.serialNumber = serialNumber; } public INTEGER getSerialNumber() { return serialNumber; } public void setSignatureAlgId(AlgorithmIdentifier signatureAlgId) { verifyNotNull(signatureAlgId); this.signatureAlgId = signatureAlgId; } public AlgorithmIdentifier getSignatureAlgId() { return signatureAlgId; } public void setIssuer(Name issuer) { verifyNotNull(issuer); this.issuer = issuer; } public Name getIssuer() { return issuer; } public void setNotBefore(Date notBefore) { verifyNotNull(notBefore); this.notBefore = notBefore; } public Date getNotBefore() { return notBefore; } public void setNotAfter(Date notAfter) { verifyNotNull(notAfter); this.notAfter = notAfter; } public Date getNotAfter() { return notAfter; } public void setSubject(Name subject) { verifyNotNull(subject); this.subject = subject; } public Name getSubject() { return subject; } public void setSubjectPublicKeyInfo( SubjectPublicKeyInfo subjectPublicKeyInfo) { verifyNotNull(subjectPublicKeyInfo); this.subjectPublicKeyInfo = subjectPublicKeyInfo; } /** * Extracts the SubjectPublicKeyInfo from the given public key and * stores it in the CertificateInfo. * * @exception InvalidBERException If an error occurs decoding the * the information extracted from the public key. */ public void setSubjectPublicKeyInfo( PublicKey pubk ) throws InvalidBERException, IOException { verifyNotNull(pubk); setSubjectPublicKeyInfo( new SubjectPublicKeyInfo(pubk) ); } public SubjectPublicKeyInfo getSubjectPublicKeyInfo() { return subjectPublicKeyInfo; } /** * @exception CertificateException If the certificate is a v1 certificate. */ public void setIssuerUniqueIdentifier(BIT_STRING issuerUniqueIdentifier) throws CertificateException { if(version==v1) { throw new CertificateException("issuerUniqueIdentifier cannot"+ " be specified for v1 certificate"); } verifyNotNull(issuerUniqueIdentifier); this.issuerUniqueIdentifier = issuerUniqueIdentifier; } public boolean hasIssuerUniqueIdentifier() { return (issuerUniqueIdentifier!=null); } /** * Should only be called if this field is present. */ public BIT_STRING getIssuerUniqueIdentifier() { assert(issuerUniqueIdentifier != null); return issuerUniqueIdentifier; } /** * @exception CertificateException If the certificate is a v1 certificate. */ public void setSubjectUniqueIdentifier(BIT_STRING subjectUniqueIdentifier) throws CertificateException { if(version==v1) { throw new CertificateException("subjectUniqueIdentifier cannot"+ " be specified for v1 certificate"); } verifyNotNull(subjectUniqueIdentifier); this.subjectUniqueIdentifier = subjectUniqueIdentifier; } public boolean hasSubjectUniqueIdentifier() { return (subjectUniqueIdentifier!=null); } public BIT_STRING getSubjectUniqueIdentifier() { assert(subjectUniqueIdentifier != null); return subjectUniqueIdentifier; } public boolean hasExtensions() { return extensions.size() > 0; } /** * Returns the extensions of this certificate. The sequence may be * empty, but this method will never return null. */ public SEQUENCE getExtensions() { return extensions; } /** * Linearly searches the extension list for an extension with the given * object identifier. If it finds one, returns true. Otherwise, * returns false. */ public boolean isExtensionPresent(OBJECT_IDENTIFIER oid) { return ( getExtension(oid) != null ); } /** * Linearly searches the extension list for an extension with the given * object identifier. It returns the first one it finds. If none are found, * returns null. */ public Extension getExtension(OBJECT_IDENTIFIER oid) { int numExtensions = extensions.size(); for( int i=0; i < numExtensions; ++i) { Extension ext = (Extension) extensions.elementAt(i); if( oid.equals(ext.getExtnId()) ) { return ext; } } return null; } /** * @exception CertificateException If the certificate is not a v3 * certificate. */ public void setExtensions(SEQUENCE extensions) throws CertificateException { if(version != v3) { throw new CertificateException("extensions can only be added to"+ " v3 certificates"); } int size = extensions.size(); for(int i=0; i < size; i++) { assert(extensions.elementAt(i) instanceof Extension); } verifyNotNull(extensions); this.extensions = extensions; } /** * @exception CertificateException If the certificate is not a v3 * certificate. */ public void addExtension(Extension extension) throws CertificateException { if(version != v3) { throw new CertificateException("extensions can only be added to"+ " v3 certificates"); } extensions.addElement(extension); } private void verifyNotNull(Object obj) { if( obj == null ) { throw new NullPointerException(); } } static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); if( version != v1 ) { // v1 is the default seq.addElement(new EXPLICIT( new Tag(0), new INTEGER(version.getNumber()) ) ); } seq.addElement(serialNumber); seq.addElement(signatureAlgId); seq.addElement(issuer); SEQUENCE validity = new SEQUENCE(); validity.addElement( encodeValidityDate(notBefore) ); validity.addElement( encodeValidityDate(notAfter) ); seq.addElement(validity); seq.addElement(subject); seq.addElement(subjectPublicKeyInfo); if( issuerUniqueIdentifier != null ) { seq.addElement(new Tag(1), issuerUniqueIdentifier); } if( subjectUniqueIdentifier != null ) { seq.addElement(new Tag(2), subjectUniqueIdentifier); } if( extensions.size() > 0 ) { seq.addElement(new EXPLICIT(new Tag(3), extensions) ); } seq.encode(implicitTag, ostream); } /** * Returns the correct ASN1Value (UTCTime or GeneralizedTime) to represent * the given certificate validity date. */ private static ASN1Value encodeValidityDate(Date d) { Calendar cal = Calendar.getInstance( TimeZone.getTimeZone("GMT") ); cal.setTime(d); if( cal.get(Calendar.YEAR) <= UTCTIME_CUTOFF_YEAR) { return new UTCTime(d); } else { return new GeneralizedTime(d); } } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } public void print(PrintStream ps) throws IOException, InvalidBERException { ps.println("CertificateInfo:"); ps.println("Version: "+version); ps.println("Serial Number: "+serialNumber); ps.println("Sig OID: "+signatureAlgId.getOID()); ps.println("Issuer: "+issuer.getRFC1485()); ps.println("Not Before: "+notBefore); ps.println("Not After: "+notAfter); ps.println("Subject: "+subject.getRFC1485()); } /** * Template class for decoding a CertificateInfo. */ public static class Template implements ASN1Template { SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); EXPLICIT.Template versionTemp = EXPLICIT.getTemplate( new Tag(0), INTEGER.getTemplate() ); EXPLICIT defVersion = new EXPLICIT(new Tag(0), new INTEGER(v1.getNumber()) ); seqt.addElement( versionTemp, defVersion ); seqt.addElement(INTEGER.getTemplate()); //serial number seqt.addElement(AlgorithmIdentifier.getTemplate()); //signatureAlgId seqt.addElement(Name.getTemplate()); // issuer // deal with validity SEQUENCE.Template validity = new SEQUENCE.Template(); CHOICE.Template timeChoice = CHOICE.getTemplate(); timeChoice.addElement( UTCTime.getTemplate() ); timeChoice.addElement( GeneralizedTime.getTemplate() ); validity.addElement( timeChoice ); // notBefore validity.addElement( timeChoice ); // notAfter seqt.addElement(validity); seqt.addElement(Name.getTemplate()); //subject seqt.addElement(SubjectPublicKeyInfo.getTemplate()); seqt.addOptionalElement( new Tag(1), BIT_STRING.getTemplate() ); seqt.addOptionalElement( new Tag(2), BIT_STRING.getTemplate() ); // deal with extensions SEQUENCE.OF_Template extnTemp = new SEQUENCE.OF_Template( Extension.getTemplate() ); seqt.addOptionalElement( new EXPLICIT.Template( new Tag(3), extnTemp) ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { try { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); EXPLICIT exp = (EXPLICIT) seq.elementAt(0); Version version = Version.fromInt( ((INTEGER)exp.getContent()).intValue() ); SEQUENCE validity = (SEQUENCE) seq.elementAt(4); CHOICE choice = (CHOICE)validity.elementAt(0); Date notBefore = ((TimeBase)choice.getValue()).toDate(); choice = (CHOICE)validity.elementAt(1); Date notAfter = ((TimeBase)choice.getValue()).toDate(); CertificateInfo cinfo = new CertificateInfo( version, (INTEGER) seq.elementAt(1), // serial num (AlgorithmIdentifier) seq.elementAt(2), //sigAlgId (Name) seq.elementAt(3), // issuer notBefore, notAfter, (Name) seq.elementAt(5), // subject (SubjectPublicKeyInfo) seq.elementAt(6) ); if( seq.elementAt(7) != null ) { cinfo.setIssuerUniqueIdentifier( (BIT_STRING)seq.elementAt(7) ); } if( seq.elementAt(8) != null ) { cinfo.setSubjectUniqueIdentifier( (BIT_STRING)seq.elementAt(8)); } if( seq.elementAt(9) != null ) { exp = (EXPLICIT)seq.elementAt(9); cinfo.setExtensions( (SEQUENCE) exp.getContent() ); } return cinfo; } catch( CertificateException e ) { throw new InvalidBERException(e.getMessage()); } } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cert/Extension.java000066400000000000000000000061621412550063600245420ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cert; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BOOLEAN; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; public class Extension implements ASN1Value { public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } private OBJECT_IDENTIFIER extnId; /** * Returns the extension identifier. */ public OBJECT_IDENTIFIER getExtnId() { return extnId; } private boolean critical; public boolean getCritical() { return critical; } private OCTET_STRING extnValue; public OCTET_STRING getExtnValue() { return extnValue; } public Extension( OBJECT_IDENTIFIER extnId, boolean critical, OCTET_STRING extnValue ) { this.extnId = extnId; this.critical = critical; this.extnValue = extnValue; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicit, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); seq.addElement( extnId ); if( critical == true ) { // false is default, so we only code true seq.addElement( new BOOLEAN(true) ); } seq.addElement( extnValue ); seq.encode(implicit, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( OBJECT_IDENTIFIER.getTemplate() ); seqt.addElement( BOOLEAN.getTemplate(), new BOOLEAN(false) ); seqt.addElement( OCTET_STRING.getTemplate() ); } @Override public boolean tagMatch(Tag t) { return TAG.equals(t); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicit, InputStream istream) throws IOException, InvalidBERException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); return new Extension( (OBJECT_IDENTIFIER) seq.elementAt(0), ((BOOLEAN) seq.elementAt(1)).toBoolean(), (OCTET_STRING) seq.elementAt(2) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cert/SubjectKeyIdentifier.java000066400000000000000000000060531412550063600266400ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cert; import java.io.IOException; import java.io.InputStream; import org.mozilla.jss.asn1.*; /** * Represent the Subject Key Identifier Extension. * * This extension, if present, provides a means of identifying the particular * public key used in an application. This extension by default is marked * non-critical. * *

Extensions are additional attributes which can be inserted in a X509 * v3 certificate. For example a "Driving License Certificate" could have * the driving license number as a extension. * *

Extensions are represented as a sequence of the extension identifier * (Object Identifier), a boolean flag stating whether the extension is to * be treated as being critical and the extension value itself (this is again * a DER encoding of the extension value). * * @author Michelle Zhao * @version 1.0 * @see Extension */ public class SubjectKeyIdentifier extends Extension { /////////////////////////////////////////////////////////////////////// // Members /////////////////////////////////////////////////////////////////////// private OCTET_STRING keyIdentifier; private static OBJECT_IDENTIFIER OID = new OBJECT_IDENTIFIER("2.5.29.14"); /////////////////////////////////////////////////////////////////////// // Construction /////////////////////////////////////////////////////////////////////// /** * Constructs an SubjectKeyIdentifier from its components. * * @param keyIdentifier must not be null. */ public SubjectKeyIdentifier(OCTET_STRING keyIdentifier) { super(OID,false,keyIdentifier); } public SubjectKeyIdentifier(boolean critical, OCTET_STRING keyIdentifier) { super(OID,critical,keyIdentifier); } public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( OBJECT_IDENTIFIER.getTemplate() ); seqt.addElement( BOOLEAN.getTemplate(), new BOOLEAN(false) ); seqt.addElement( OCTET_STRING.getTemplate() ); } @Override public boolean tagMatch(Tag t) { return TAG.equals(t); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicit, InputStream istream) throws IOException, InvalidBERException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); assert( ((OBJECT_IDENTIFIER) seq.elementAt(0)).equals(OID) ); return new SubjectKeyIdentifier( ((BOOLEAN) seq.elementAt(1)).toBoolean(), (OCTET_STRING) seq.elementAt(2) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cert/package.html000066400000000000000000000004671412550063600242060ustar00rootroot00000000000000 Encoding and decoding X.509 certificates and certificate extensions. jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/000077500000000000000000000000001412550063600215235ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/BodyPartReference.java000066400000000000000000000150021412550063600257270ustar00rootroot00000000000000/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * 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 Services for Java. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 2004 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.jss.pkix.cmc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.CHOICE; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * CMC BodyPartReference: *

 *      BodyPartReference::= CHOICE {
 *          bodyPartID       BodyPartID
 *          bodyPartPath     SEQUENCE SIZE (1..MAX) OF BodyPartID,
 *     }
 *
 * @author Christina Fu (cfu)
 * 
*/ public class BodyPartReference implements ASN1Value { public static final INTEGER BODYIDMAX = new INTEGER("4294967295"); /** * The type of BodyPartReference. */ public static class Type { private Type() { } static Type BodyPartID = new Type(); static Type BodyPartPath = new Type(); } public static Type BodyPartID = Type.BodyPartID; public static Type BodyPartPath = Type.BodyPartPath; /////////////////////////////////////////////////////////////////////// // Members /////////////////////////////////////////////////////////////////////// private Type type; private INTEGER bodyPartID; private SEQUENCE bodyPartPath; /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * @param type The type of the BodyPartReference * @param bodyPartID A BodyPartID. * @param bodyPartPath The sequence of bodyPartIDs. */ public BodyPartReference(Type type, INTEGER bodyPartID, SEQUENCE bodyPartPath) { this.bodyPartID = bodyPartID; this.bodyPartPath = bodyPartPath; } /** * Adds a BodyPartID to the bodyPartPath SEQUENCE. */ public void addBodyPartId(int id) { INTEGER id1 = new INTEGER(id); assert(id1.compareTo(BODYIDMAX) <= 0); bodyPartPath.addElement( id1 ); } /////////////////////////////////////////////////////////////////////// // member access /////////////////////////////////////////////////////////////////////// /** * Returns the type of BodyPartReference:
    *
  • BodyPartID *
  • BodyPartPath *
*/ public Type getType() { return type; } public INTEGER getBodyPartID() { return bodyPartID; } public SEQUENCE getBodyPartPath() { return bodyPartPath; } /////////////////////////////////////////////////////////////////////// // decoding/encoding /////////////////////////////////////////////////////////////////////// @Override public Tag getTag() { //return the subType's tag if (type == BodyPartID ) { return INTEGER.TAG; } else { assert( type == BodyPartPath); return SEQUENCE.TAG; } } @Override public void encode(OutputStream ostream) throws IOException { if (type == BodyPartID ) { bodyPartID.encode(ostream); } else { assert( type == BodyPartPath); bodyPartPath.encode(ostream); } } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { encode(ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template for decoding a BodyPartReference. */ public static class Template implements ASN1Template { private CHOICE.Template choicet; public Template() { choicet = new CHOICE.Template(); choicet.addElement( INTEGER.getTemplate() ); choicet.addElement( new SEQUENCE.OF_Template(INTEGER.getTemplate()) ); } @Override public boolean tagMatch(Tag tag) { return choicet.tagMatch(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { CHOICE c = (CHOICE) choicet.decode(istream); if( c.getTag().equals(INTEGER.TAG) ) { return new BodyPartReference(BodyPartID, (INTEGER) c.getValue() , null); } else { assert( c.getTag().equals(SEQUENCE.TAG) ); return new BodyPartReference(BodyPartPath, null, (SEQUENCE) c.getValue()); } } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { //A CHOICE cannot be implicitly tagged return decode(istream); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/CMCCertId.java000066400000000000000000000122731412550063600240700ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BIT_STRING; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * CMC CMCCertId. *
 * The definition of IssuerSerial comes from RFC 3281.
 * CMCCertId ::= SEQUENCE {
 *      issuer      GeneralNames,
 *      serial      INTEGER
 *      issuerUID   UniqueIdentifier OPTIONAL}
 * 
*/ public class CMCCertId implements ASN1Value { /////////////////////////////////////////////////////////////////////// // Members and member access /////////////////////////////////////////////////////////////////////// private SEQUENCE issuer; private INTEGER serial; private BIT_STRING issuerUID; private SEQUENCE sequence; /** * Returns the issuer field as an SEQUENCE of * ANY. The actual type of the field is GeneralNames. */ public SEQUENCE getIssuer() { return issuer; } /** * Returns the serial field. */ public INTEGER getSerial() { return serial; } /** * Returns the issuerUID field. */ public BIT_STRING getIssuerUID() { return issuerUID; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * Constructs a new CMCCertId from its components. The * uniqueIdentifier component may be null. */ public CMCCertId(SEQUENCE issuer, INTEGER serial, BIT_STRING issuerUID) { if (issuer == null || serial == null) { throw new IllegalArgumentException( "parameter to CMCCertId constructor is null"); } if (issuer.size() == 0) { throw new IllegalArgumentException( "issuer parameter to CMCCertId constructor is empty"); } sequence = new SEQUENCE(); this.issuer = issuer; sequence.addElement(issuer); this.serial = serial; sequence.addElement(serial); if (issuerUID != null) { sequence.addElement(issuerUID); } } /** * Constructs a new CMCCertId from its components. The * issuerUID component may be null. */ public CMCCertId(ANY issuer, INTEGER serial, BIT_STRING issuerUID) { if (issuer == null || serial == null) { throw new IllegalArgumentException( "parameter to CMCCertId constructor is null"); } sequence = new SEQUENCE(); this.issuer = new SEQUENCE(); this.issuer.addElement(issuer); sequence.addElement(this.issuer); this.serial = serial; sequence.addElement(serial); if (issuerUID != null) { sequence.addElement(issuerUID); } } /////////////////////////////////////////////////////////////////////// // encoding/decoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template for decoding a CMCCertId. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement(new SEQUENCE.OF_Template(ANY.getTemplate())); seqt.addElement( INTEGER.getTemplate() ); seqt.addOptionalElement(BIT_STRING.getTemplate()); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new CMCCertId((SEQUENCE)seq.elementAt(0), (INTEGER)seq.elementAt(1), (BIT_STRING)seq.elementAt(2)); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/CMCStatusInfo.java000066400000000000000000000151541412550063600250160ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.asn1.UTF8String; /** * CMC CMCStatusInfo: *
 *     CMCStatusInfo ::= SEQUENCE {
 *          cMCStatus           CMCStatus,
 *          bodyList            SEQUENCE SIZE (1..MAX) OF BodyPartID,
 *          statusString        UTF8String OPTIONAL,
 *          otherInfo           CHOICE {
 *            failInfo            CMCFailInfo,
 *            pendInfo            PendInfo } OPTIONAL
 *     }
 *     PendInfo ::= SEQUENCE {
 *          pendToken           OCTET STRING,
 *          pendTime            GeneralizedTime
 *     }
 * 
*/ public class CMCStatusInfo implements ASN1Value { public static final INTEGER BODYIDMAX = new INTEGER("4294967295"); /////////////////////////////////////////////////////////////////////// // Members /////////////////////////////////////////////////////////////////////// private INTEGER status; private SEQUENCE bodyList; private UTF8String statusString; private OtherInfo otherInfo; // CMCStatus constants public static final int SUCCESS = 0; public static final int RESERVED = 1; public static final int FAILED = 2; public static final int PENDING = 3; public static final int NOSUPPORT = 4; public static final int CONFIRM_REQUIRED = 5; public static final String[] STATUS = {"success", "reserved", "failed", "pending", "not supported", "confirm required"}; /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * @param status A CMCStatus constant. * @param bodyList The sequence of bodyPartID. */ public CMCStatusInfo(int status, SEQUENCE bodyList) { this.status = new INTEGER(status); this.bodyList = bodyList; this.statusString = null; this.otherInfo = null; } /** * @param status A CMCStatus constant. * @param bodyList The sequence of bodyPartID. * @param statusString A String. * @param otherInfo The OtherInfo choice. */ public CMCStatusInfo(int status, SEQUENCE bodyList, String statusString, OtherInfo otherInfo) { this.status = new INTEGER(status); this.bodyList = bodyList; if (statusString != null){ try{ this.statusString = new UTF8String(statusString); }catch (Exception e){} }else this.statusString = null; this.otherInfo = otherInfo; } /** * Create a CMCStatusInfo from decoding. * @param status A CMCStatus constant. * @param bodyList The sequence of bodyPartID. * @param statusString A UTF8String. * @param otherInfo A CHOICE. */ public CMCStatusInfo(INTEGER status, SEQUENCE bodyList, UTF8String statusString, OtherInfo otherInfo) { this.status = status; this.bodyList = bodyList; this.statusString = statusString; this.otherInfo = otherInfo; } /** * Sets the statusString field. May be null, since this * field is optional. */ public void setStatusString(String statusString) { if (statusString != null){ try{ this.statusString = new UTF8String(statusString); }catch (Exception e){} }else{ this.statusString = null; } } /** * Adds a BodyPartID to the bodyList SEQUENCE. */ public void addBodyPartID(int id) { INTEGER id1 = new INTEGER(id); assert(id1.compareTo(BODYIDMAX) <= 0); bodyList.addElement( id1 ); } /////////////////////////////////////////////////////////////////////// // member access /////////////////////////////////////////////////////////////////////// public int getStatus() { return status.intValue(); } public SEQUENCE getBodyList() { return bodyList; } public String getStatusString() { if (statusString != null) return statusString.toString(); return null; } public OtherInfo getOtherInfo() { return otherInfo; } /////////////////////////////////////////////////////////////////////// // decoding/encoding /////////////////////////////////////////////////////////////////////// public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); seq.addElement(status); seq.addElement(bodyList); if( statusString != null ) { seq.addElement( statusString ); } if ( otherInfo != null) { seq.addElement( otherInfo ); } seq.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( INTEGER.getTemplate() ); seqt.addElement( new SEQUENCE.OF_Template(INTEGER.getTemplate()) ); seqt.addOptionalElement( UTF8String.getTemplate()); seqt.addOptionalElement( OtherInfo.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { CMCStatusInfo psi; SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new CMCStatusInfo((INTEGER)seq.elementAt(0), (SEQUENCE)seq.elementAt(1), (UTF8String)seq.elementAt(2), (OtherInfo)seq.elementAt(3)); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/CMCStatusInfoV2.java000066400000000000000000000222571412550063600252300ustar00rootroot00000000000000/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * 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 Services for Java. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.jss.pkix.cmc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.asn1.UTF8String; /** * CMCStatusInfoV2 replaces CMCStatusInfo in rfc 5272 * CMC CMCStatusInfoV2: *
 *     CMCStatusInfoV2 ::= SEQUENCE {
 *          cMCStatus           CMCStatus,
 *          bodyList            SEQUENCE SIZE (1..MAX)
 *                                       BodyPartReference,
 *          statusString        UTF8String OPTIONAL,
 *          otherInfo           CHOICE {  // defined in updated OtherInfo
 *            failInfo            CMCFailInfo,
 *            pendInfo            PendInfo,
 *            extendedFailInfo       SEQUENCE {
 *              failInfoOID            OBJECT IDENTIFIER,
 *              failInfoValue          AttributeValue
 *            } OPTIONAL
 *         }
 *     }
 *     PendInfo ::= SEQUENCE {
 *          pendToken           OCTET STRING,
 *          pendTime            GeneralizedTime
 *     }
 *
 * @author Christina Fu (cfu)
 * 
*/ public class CMCStatusInfoV2 implements ASN1Value { public static final INTEGER BODYIDMAX = new INTEGER("4294967295"); /////////////////////////////////////////////////////////////////////// // Members /////////////////////////////////////////////////////////////////////// private INTEGER status; private SEQUENCE bodyList; private UTF8String statusString; private OtherInfo otherInfo; // CMCStatus constants public static final int SUCCESS = 0; public static final int RESERVED = 1; public static final int FAILED = 2; public static final int PENDING = 3; public static final int NOSUPPORT = 4; public static final int CONFIRM_REQUIRED = 5; public static final int POP_REQUIRED = 6; public static final int PARTIAL = 7; public static final String[] STATUS = {"success", "reserved", "failed", "pending", "not supported", "confirm required", "pop required", "partial"}; /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * @param status A CMCStatus constant. * @param bodyList The sequence of BodyPartReference. */ public CMCStatusInfoV2(int status, SEQUENCE bodyList) { this.status = new INTEGER(status); this.bodyList = bodyList; this.statusString = null; this.otherInfo = null; } /** * @param status A CMCStatus constant. * @param bodyList The sequence of BodyPartReference. * @param statusString A String. * @param otherInfo The OtherInfo choice. */ public CMCStatusInfoV2(int status, SEQUENCE bodyList, String statusString, OtherInfo otherInfo) { this.status = new INTEGER(status); this.bodyList = bodyList; if (statusString != null){ try { this.statusString = new UTF8String(statusString); } catch (Exception e){} } else this.statusString = null; this.otherInfo = otherInfo; } /** * Create a CMCStatusInfoV2 from decoding. * @param status A CMCStatus constant. * @param bodyList The sequence of BodyPartReference. * @param statusString A UTF8String. * @param otherInfo A CHOICE. */ public CMCStatusInfoV2(INTEGER status, SEQUENCE bodyList, UTF8String statusString, OtherInfo otherInfo) { this.status = status; this.bodyList = bodyList; this.statusString = statusString; this.otherInfo = otherInfo; } /** * Sets the statusString field. May be null, since this * field is optional. */ public void setStatusString(String statusString) { if (statusString != null){ try { this.statusString = new UTF8String(statusString); } catch (Exception e){} } else{ this.statusString = null; } } /** * Adds a BodyPartID to the bodyList SEQUENCE. */ public void addBodyPartID(int id) { INTEGER id1 = new INTEGER(id); assert(id1.compareTo(BODYIDMAX) <= 0); bodyList.addElement( id1 ); } /////////////////////////////////////////////////////////////////////// // member access /////////////////////////////////////////////////////////////////////// public int getStatus() { return status.intValue(); } public SEQUENCE getBodyList() { return bodyList; } public String getStatusString() { if (statusString != null) return statusString.toString(); return null; } public OtherInfo getOtherInfo() { return otherInfo; } /////////////////////////////////////////////////////////////////////// // decoding/encoding /////////////////////////////////////////////////////////////////////// public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); seq.addElement(status); seq.addElement(bodyList); if( statusString != null ) { seq.addElement( statusString ); } if ( otherInfo != null) { seq.addElement( otherInfo ); } seq.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( INTEGER.getTemplate() ); seqt.addElement( new SEQUENCE.OF_Template(INTEGER.getTemplate()) ); seqt.addOptionalElement( UTF8String.getTemplate()); seqt.addOptionalElement( OtherInfo.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { CMCStatusInfoV2 psi; SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new CMCStatusInfoV2((INTEGER)seq.elementAt(0), (SEQUENCE)seq.elementAt(1), (UTF8String)seq.elementAt(2), (OtherInfo)seq.elementAt(3)); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/DecryptedPOP.java000066400000000000000000000133351412550063600246750ustar00rootroot00000000000000/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * 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 Services for Java. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.jss.pkix.cmc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; /** * CMC DecryptedPOP: *
 *     DecryptedPOP ::= SEQUENCE {
 *         bodyPartID      BodyPartID,
 *         thePOPAlgID     AlgorithmIdentifier,
 *         thePOP         OCTET STRING
 *     }
 * 
* * @author Christina Fu (cfu) */ public class DecryptedPOP implements ASN1Value { /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private INTEGER bodyPartID; private AlgorithmIdentifier thePOPAlgID; private OCTET_STRING thePOP; private SEQUENCE sequence; // for DER encoding /** * Returns the bodyPartID field. */ public INTEGER getBodyPartID() { return bodyPartID; } public AlgorithmIdentifier getThePOPAlgID() { return thePOPAlgID; } public OCTET_STRING getWitness() { return thePOP; } /////////////////////////////////////////////////////////////////////// // constructors /////////////////////////////////////////////////////////////////////// public DecryptedPOP( INTEGER bodyPartID, AlgorithmIdentifier thePOPAlgID, OCTET_STRING thePOP) { if( bodyPartID==null || thePOPAlgID==null || thePOP==null ) { throw new IllegalArgumentException("DecryptedPOP constructor" +" parameter is null"); } this.bodyPartID = bodyPartID; this.thePOPAlgID = thePOPAlgID; this.thePOP = thePOP; sequence = new SEQUENCE(); sequence.addElement(bodyPartID); sequence.addElement(thePOPAlgID); sequence.addElement(thePOP); } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template for decoding BER-encoded DecryptedPOP items. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( INTEGER.getTemplate() ); seqt.addElement( AlgorithmIdentifier.getTemplate() ); seqt.addElement( OCTET_STRING.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new DecryptedPOP( (INTEGER) seq.elementAt(0), (AlgorithmIdentifier) seq.elementAt(1), (OCTET_STRING) seq.elementAt(2) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/EncryptedPOP.java000066400000000000000000000147521412550063600247130ustar00rootroot00000000000000/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * 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 Services for Java. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.jss.pkix.cmc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.pkix.cms.ContentInfo; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; /** * CMC EncryptedPOP: *
 *     EncryptedPOP ::= SEQUENCE {
 *         request       TaggedRequest,
 *         cms             ContentInfo,
 *         thePOPAlgID     AlgorithmIdentifier,
 *         witnessAlgID    AlgorithmIdentifier,
 *         witness         OCTET STRING
 *     }
 * 
* * @author Christina Fu (cfu) */ public class EncryptedPOP implements ASN1Value { /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private TaggedRequest request; private ContentInfo cms; private AlgorithmIdentifier thePOPAlgID; private AlgorithmIdentifier witnessAlgID; private OCTET_STRING witness; private SEQUENCE sequence; // for DER encoding public TaggedRequest getRequest() { return request; } public ContentInfo getContentInfo() { return cms; } public AlgorithmIdentifier getThePOPAlgID() { return thePOPAlgID; } public AlgorithmIdentifier getWitnessAlgID() { return witnessAlgID; } public OCTET_STRING getWitness() { return witness; } /////////////////////////////////////////////////////////////////////// // constructors /////////////////////////////////////////////////////////////////////// public EncryptedPOP( TaggedRequest request, ContentInfo cms, AlgorithmIdentifier thePOPAlgID, AlgorithmIdentifier witnessAlgID, OCTET_STRING witness) { if( request==null || cms==null || thePOPAlgID==null || witnessAlgID==null || witness==null ) { throw new IllegalArgumentException("EncryptedPOP constructor" +" parameter is null"); } this.request = request; this.cms = cms; this.thePOPAlgID = thePOPAlgID; this.witnessAlgID = witnessAlgID; this.witness = witness; sequence = new SEQUENCE(); sequence.addElement(request); sequence.addElement(cms); sequence.addElement(thePOPAlgID); sequence.addElement(witnessAlgID); sequence.addElement(witness); } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template for decoding BER-encoded EncryptedPOP items. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( TaggedRequest.getTemplate() ); seqt.addElement( ContentInfo.getTemplate() ); seqt.addElement( AlgorithmIdentifier.getTemplate() ); seqt.addElement( AlgorithmIdentifier.getTemplate() ); seqt.addElement( OCTET_STRING.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new EncryptedPOP( (TaggedRequest) seq.elementAt(0), (ContentInfo) seq.elementAt(1), (AlgorithmIdentifier) seq.elementAt(2), (AlgorithmIdentifier) seq.elementAt(3), (OCTET_STRING) seq.elementAt(4) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/ExtendedFailInfo.java000066400000000000000000000121001412550063600255300ustar00rootroot00000000000000/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * 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 Services for Java. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.jss.pkix.cmc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * ExtendedFailInfo per rfc 5272 * It is to be used in CMCStatusInfoV2 as a CHOICE of otherInfo * *
 *      ExtendedFailInfo ::= SEQUENCE {
 *          failInfoOID        OBJECT IDENTIFIER,
 *          failInfoValue       ANY DEFINED BY failInfoOID }
 * 
* * @author Christina Fu (cfu) */ public class ExtendedFailInfo implements ASN1Value { private OBJECT_IDENTIFIER failInfoOID; private ANY failInfoValue; public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } public ExtendedFailInfo(OBJECT_IDENTIFIER failInfoOID, ASN1Value failInfoValue) { this.failInfoOID = failInfoOID; if( failInfoValue instanceof ANY ) { this.failInfoValue = (ANY) failInfoValue; } else { byte[] encoded = ASN1Util.encode(failInfoValue); try { this.failInfoValue = (ANY) ASN1Util.decode(ANY.getTemplate(), encoded); } catch( InvalidBERException e ) { throw new RuntimeException("InvalidBERException while decoding as ANY: " + e.getMessage(), e); } } } public OBJECT_IDENTIFIER getOID() { return failInfoOID; } /** * Returns the failInfoValue of this ExtendedFailInfo, encoded as an ANY. */ public ANY getValue() { return failInfoValue; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicit, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); seq.addElement(failInfoOID); seq.addElement(failInfoValue); seq.encode(implicit, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template for decoding an ExtendedFailInfo. */ public static class Template implements ASN1Template { @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicit, InputStream istream) throws IOException, InvalidBERException { SEQUENCE.Template seqt = new SEQUENCE.Template(); seqt.addElement( new OBJECT_IDENTIFIER.Template() ); seqt.addElement( new ANY.Template() ); SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); // The template should have enforced this assert(seq.size() == 2); return new ExtendedFailInfo( (OBJECT_IDENTIFIER) seq.elementAt(0), seq.elementAt(1) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/GetCert.java000066400000000000000000000075151412550063600237330ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * CMC GetCert. *
 * GetCert ::= SEQUENCE {
 *      issuerName      GeneralName,
 *      serialNumber    INTEGER }
 * 
*/ public class GetCert implements ASN1Value { /////////////////////////////////////////////////////////////////////// // Members and member access /////////////////////////////////////////////////////////////////////// private ANY issuerName; private INTEGER serialNumber; private SEQUENCE sequence; /** * Returns the issuerName field as an ANY. * The actual type of the field is GeneralName. */ public ANY getIssuer() { return issuerName; } /** * Returns the serialNumber field. */ public INTEGER getSerialNumber() { return serialNumber; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * Constructs a new GetCert from its components. Neither * component may be null. */ public GetCert(ANY issuerName, INTEGER serialNumber) { if( issuerName == null || serialNumber == null ) { throw new IllegalArgumentException( "parameter to GetCert constructor is null"); } sequence = new SEQUENCE(); this.issuerName = issuerName; sequence.addElement(issuerName); this.serialNumber = serialNumber; sequence.addElement(serialNumber); } /////////////////////////////////////////////////////////////////////// // encoding/decoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template for decoding a GetCert. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( ANY.getTemplate() ); seqt.addElement( INTEGER.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new GetCert( (ANY) seq.elementAt(0), (INTEGER) seq.elementAt(1) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/IdentityProofV2.java000066400000000000000000000133101412550063600253730ustar00rootroot00000000000000/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * 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 Services for Java. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.jss.pkix.cmc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; /** * CMC IdentityProofV2: * per rfc 5272 *
 *     IdentityProofV2 ::= SEQUENCE {
 *         hashAlgID      AlgorithmIdentifier,
 *         macAlgId       AlgorithmIdentifier,
 *         witness        OCTET STRING
 *     }
 * 
* * @author Christina Fu (cfu) */ public class IdentityProofV2 implements ASN1Value { /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private AlgorithmIdentifier hashAlgID; private AlgorithmIdentifier macAlgId; private OCTET_STRING witness; private SEQUENCE sequence; // for DER encoding public AlgorithmIdentifier getHashAlgID() { return hashAlgID; } public AlgorithmIdentifier getMacAlgId() { return macAlgId; } public OCTET_STRING getWitness() { return witness; } /////////////////////////////////////////////////////////////////////// // constructors /////////////////////////////////////////////////////////////////////// public IdentityProofV2( AlgorithmIdentifier hashAlgID, AlgorithmIdentifier macAlgId, OCTET_STRING witness) { if( hashAlgID==null || macAlgId==null || witness==null ) { throw new IllegalArgumentException("IdentityProofV2 constructor" +" parameter is null"); } this.hashAlgID = hashAlgID; this.macAlgId = macAlgId; this.witness = witness; sequence = new SEQUENCE(); sequence.addElement(hashAlgID); sequence.addElement(macAlgId); sequence.addElement(witness); } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template for decoding BER-encoded IdentityProofV2 items. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( AlgorithmIdentifier.getTemplate() ); seqt.addElement( AlgorithmIdentifier.getTemplate() ); seqt.addElement( OCTET_STRING.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new IdentityProofV2( (AlgorithmIdentifier) seq.elementAt(0), (AlgorithmIdentifier) seq.elementAt(1), (OCTET_STRING) seq.elementAt(2) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/LraPopWitness.java000066400000000000000000000100721412550063600251400ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * CMC LraPopWitness: *
 *      LraPopWitness::= SEQUENCE {
 *          pkiDataBodyid       BodyPartID
 *          bodyids             SEQUENCE SIZE (1..MAX) OF BodyPartID,
 *     }
 * 
*/ public class LraPopWitness implements ASN1Value { public static final INTEGER BODYIDMAX = new INTEGER("4294967295"); /////////////////////////////////////////////////////////////////////// // Members /////////////////////////////////////////////////////////////////////// private INTEGER pkiDataBodyid; private SEQUENCE bodyIds; private SEQUENCE sequence; /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * @param pkiDataBodyid A PKI data BodyPartID. * @param bodyIds The sequence of bodyPartIDs. */ public LraPopWitness(INTEGER pkiDataBodyid, SEQUENCE bodyIds) { if (pkiDataBodyid == null || bodyIds == null) throw new IllegalArgumentException( "parameter to LraPopWitness constructor is null"); sequence = new SEQUENCE(); this.pkiDataBodyid = pkiDataBodyid; sequence.addElement(pkiDataBodyid); this.bodyIds = bodyIds; sequence.addElement(bodyIds); } /** * Adds a BodyPartID to the bodyIds SEQUENCE. */ public void addBodyPartId(int id) { INTEGER id1 = new INTEGER(id); assert(id1.compareTo(BODYIDMAX) <= 0); bodyIds.addElement( id1 ); } /////////////////////////////////////////////////////////////////////// // member access /////////////////////////////////////////////////////////////////////// public INTEGER getPKIDataBodyid() { return pkiDataBodyid; } public SEQUENCE getBodyIds() { return bodyIds; } /////////////////////////////////////////////////////////////////////// // decoding/encoding /////////////////////////////////////////////////////////////////////// public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( INTEGER.getTemplate() ); seqt.addElement( new SEQUENCE.OF_Template(INTEGER.getTemplate()) ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new LraPopWitness((INTEGER)seq.elementAt(0), (SEQUENCE)seq.elementAt(1)); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/OtherInfo.java000066400000000000000000000214341412550063600242670ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmc; import org.mozilla.jss.asn1.*; import java.io.*; /** * CMCStatusInfoV2 OtherInfo: * *
 *   OtherInfo ::= CHOICE { 
 *       failInfo INTEGER, 
 *       pendInfo PendInfo,
 *       extendedFailInfo       SEQUENCE {  // ExtendedFailInfo
 *           failInfoOID            OBJECT IDENTIFIER,
 *           failInfoValue          AttributeValue
 *       } OPTIONAL
 *   }
 * 
* * @author Christina Fu (cfu) - updated for rfc5272 */ public class OtherInfo implements ASN1Value { // CMCFailInfo constants public static final int BAD_ALG = 0; public static final int BAD_MESSAGE_CHECK = 1; public static final int BAD_REQUEST = 2; public static final int BAD_TIME = 3; public static final int BAD_CERT_ID = 4; public static final int UNSUPORTED_EXT = 5; public static final int MUST_ARCHIVE_KEYS = 6; public static final int BAD_IDENTITY = 7; public static final int POP_REQUIRED = 8; public static final int POP_FAILED = 9; public static final int NO_KEY_REUSE = 10; public static final int INTERNAL_CA_ERROR = 11; public static final int TRY_LATER = 12; public static final int authDataFail = 13; public static final String[] FAIL_INFO = { "bad algorithm", "bad message check", "bad request", "bad time", "bad certificate id", "unsupported extensions", "must archive keys", "bad identity", "POP required", "POP failed", "no key reuse", "internal ca error", "try later", "authenticated data fail"}; /** * The type of OtherInfo. */ public static class Type { private Type() { } static Type FAIL = new Type(); static Type PEND = new Type(); static Type EXTENDED = new Type(); } public static Type FAIL = Type.FAIL; public static Type PEND = Type.PEND; public static Type EXTENDED = Type.EXTENDED; /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private Type type; private INTEGER failInfo; // if type == FAIL private PendInfo pendInfo; // if type == PEND private ExtendedFailInfo extendedFailInfo; // if type == EXTENDED /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// // no default constructor public OtherInfo() { } /** * Constructs a OtherInfo from its components. * * @param type The type of the otherInfo. * @param failInfo the CMCFailInfo code. * @param pendInfo the pending information. * * Note: kept for backward compatibility for now; new code don't use */ public OtherInfo(Type type, INTEGER failInfo, PendInfo pendInfo) { if (type == null) { throw new IllegalArgumentException("OtherInfo constructor" +" parameter is null"); } if ( type == FAIL ) { if (failInfo == null) { throw new IllegalArgumentException("OtherInfo constructor" +" parameter failInfo is null"); } } else { assert( type == PEND ); if (pendInfo == null) { throw new IllegalArgumentException("OtherInfo constructor" +" parameter pendInfo is null"); } } this.type = type; this.failInfo = failInfo; this.pendInfo = pendInfo; } /** * Constructs a OtherInfo from its components. * * @param type The type of the otherInfo. * @param failInfo the CMCFailInfo code. * @param pendInfo the pending information. * @param extendedFailInfo the extendedFailInfo information. */ public OtherInfo(Type type, INTEGER failInfo, PendInfo pendInfo, ExtendedFailInfo extendedFailInfo) { if (type == null) { throw new IllegalArgumentException("OtherInfo constructor" +" parameter is null"); } if ( type == FAIL ) { if (failInfo == null) { throw new IllegalArgumentException("OtherInfo constructor" +" parameter failInfo is null"); } } else if ( type == PEND ) { if (pendInfo == null) { throw new IllegalArgumentException("OtherInfo constructor" +" parameter pendInfo is null"); } } else { assert( type == EXTENDED ); if (extendedFailInfo == null) { throw new IllegalArgumentException("OtherInfo constructor" +" parameter extendedFailInfo is null"); } } this.type = type; this.failInfo = failInfo; this.pendInfo = pendInfo; this.extendedFailInfo = extendedFailInfo; } /////////////////////////////////////////////////////////////////////// // accessors /////////////////////////////////////////////////////////////////////// /** * Returns the type of OtherInfo:
    *
  • FAIL *
  • PEND *
  • EXTENDED *
*/ public Type getType() { return type; } /** * If type == FAIL, returns the failInfo field. Otherwise, * returns null. */ public INTEGER getFailInfo() { return failInfo; } /** * If type == PEND, returns the pendInfo field. Otherwise, * returns null. */ public PendInfo getPendInfo() { return pendInfo; } /** * If type == EXTENDED, returns the extendedFailInfo field. Otherwise, * returns null. */ public ExtendedFailInfo getExtendedFailInfo() { return extendedFailInfo; } /////////////////////////////////////////////////////////////////////// // DER decoding/encoding /////////////////////////////////////////////////////////////////////// @Override public Tag getTag() { // return the subType's tag if( type == FAIL ) { return INTEGER.TAG; } else if( type == PEND ){ return PendInfo.TAG; } else { assert( type == EXTENDED ); return ExtendedFailInfo.TAG; } } @Override public void encode(OutputStream ostream) throws IOException { if( type == FAIL ) { failInfo.encode(ostream); } else if( type == PEND ){ pendInfo.encode(ostream); } else { assert( type == EXTENDED ); extendedFailInfo.encode(ostream); } } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { //Assert.notReached("A CHOICE cannot be implicitly tagged " +implicitTag.getNum()); encode(ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template for decoding a OtherInfo. */ public static class Template implements ASN1Template { private CHOICE.Template choicet; public Template() { choicet = new CHOICE.Template(); choicet.addElement( INTEGER.getTemplate() ); choicet.addElement( PendInfo.getTemplate() ); choicet.addElement( ExtendedFailInfo.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return choicet.tagMatch(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { CHOICE c = (CHOICE) choicet.decode(istream); if( c.getTag().equals(INTEGER.TAG) ) { return new OtherInfo(FAIL, (INTEGER) c.getValue() , null, null); } else if( c.getTag().equals(PendInfo.TAG) ) { return new OtherInfo(PEND, null, (PendInfo) c.getValue(), null); } else { assert( c.getTag().equals(ExtendedFailInfo.TAG) ); return new OtherInfo(EXTENDED, null, null, (ExtendedFailInfo) c.getValue()); } } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { //Assert.notReached("A CHOICE cannot be implicitly tagged"); return decode(istream); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/OtherMsg.java000066400000000000000000000105331412550063600241200ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * CMC OtherMsg. *
 * The definition of OtherMsg comes from RFC 2797.
 * OtherMsg ::= SEQUENCE {
 *      bodyPartID      BodyPartID,
 *      otherMsgType    Object Identifier,
 *      otherMsgValue   ANY defined by otherMsgType}
 * 
*/ public class OtherMsg implements ASN1Value { /////////////////////////////////////////////////////////////////////// // Members and member access /////////////////////////////////////////////////////////////////////// private INTEGER bodyPartID; private OBJECT_IDENTIFIER otherMsgType; private ANY otherMsgValue; private SEQUENCE sequence; /** * Returns the bodyPartID field. */ public INTEGER getBodyPartID() { return bodyPartID; } /** * Returns the otherMsgType field. */ public OBJECT_IDENTIFIER getOtherMsgType() { return otherMsgType; } /** * Returns the otherMsgValue field. */ public ANY getOtherMsgValue() { return otherMsgValue; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * Constructs a new OtherMsg from its components. */ public OtherMsg(INTEGER bodyPartID, OBJECT_IDENTIFIER otherMsgType, ANY otherMsgValue) { if (bodyPartID == null || otherMsgType == null || otherMsgValue == null) { throw new IllegalArgumentException( "parameter to OtherMsg constructor is null"); } sequence = new SEQUENCE(); this.bodyPartID = bodyPartID; sequence.addElement(bodyPartID); this.otherMsgType = otherMsgType; sequence.addElement(otherMsgType); this.otherMsgValue = otherMsgValue; sequence.addElement(otherMsgValue); } /////////////////////////////////////////////////////////////////////// // encoding/decoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template for decoding a OtherMsg. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement(INTEGER.getTemplate()); seqt.addElement(OBJECT_IDENTIFIER.getTemplate()); seqt.addElement(ANY.getTemplate()); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new OtherMsg((INTEGER)seq.elementAt(0), (OBJECT_IDENTIFIER)seq.elementAt(1), (ANY)seq.elementAt(2)); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/OtherReqMsg.java000066400000000000000000000140611412550063600245700ustar00rootroot00000000000000/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * 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 Services for Java. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 2004 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.jss.pkix.cmc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * CMC OtherReqMsg. *
 * OtherReqMsg is to be used by the "orm" field of the TaggedRequest per
 *     definition in RFC 5272.
 *
 * OtherReqMsg ::= SEQUENCE {
 *      bodyPartID      BodyPartID,
 *      requestMessageType    Object Identifier,
 *      requestMessageValue   ANY defined by requestMessageType}
 * 
* * @author Christina Fu (cfu) */ public class OtherReqMsg implements ASN1Value { /////////////////////////////////////////////////////////////////////// // Members and member access /////////////////////////////////////////////////////////////////////// private INTEGER bodyPartID; private OBJECT_IDENTIFIER requestMessageType; private ANY requestMessageValue; private SEQUENCE sequence; /** * Returns the bodyPartID field. */ public INTEGER getBodyPartID() { return bodyPartID; } /** * Returns the requestMessageType field. */ public OBJECT_IDENTIFIER getOtherReqMsgType() { return requestMessageType; } /** * Returns the requestMessageValue field. */ public ANY getOtherReqMsgValue() { return requestMessageValue; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * Constructs a new OtherReqMsg from its components. */ public OtherReqMsg(INTEGER bodyPartID, OBJECT_IDENTIFIER requestMessageType, ANY requestMessageValue) { if (bodyPartID == null || requestMessageType == null || requestMessageValue == null) { throw new IllegalArgumentException( "parameter to OtherReqMsg constructor is null"); } sequence = new SEQUENCE(); this.bodyPartID = bodyPartID; sequence.addElement(bodyPartID); this.requestMessageType = requestMessageType; sequence.addElement(requestMessageType); this.requestMessageValue = requestMessageValue; sequence.addElement(requestMessageValue); } /////////////////////////////////////////////////////////////////////// // encoding/decoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template for decoding a OtherReqMsg. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement(INTEGER.getTemplate()); seqt.addElement(OBJECT_IDENTIFIER.getTemplate()); seqt.addElement(ANY.getTemplate()); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new OtherReqMsg((INTEGER)seq.elementAt(0), (OBJECT_IDENTIFIER)seq.elementAt(1), (ANY)seq.elementAt(2)); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/PKIData.java000066400000000000000000000115171412550063600236100ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * A PKIData for CMC full enrollment request. * PKIData ::= SEQUENCE { * controlSequence SEQUENCE SIZE(0..MAX) OF TaggedAttribute, * reqSequence SEQUENCE SIZE(0..MAX) OF TaggedRequest, * cmsSequence SEQUENCE SIZE(0..MAX) OF TaggedContentInfo, * otherMsgSequence SEQUENCE SIZE(0..MAX) OF OtherMsg * } */ public class PKIData implements ASN1Value { /////////////////////////////////////////////////////////////////////// // Members /////////////////////////////////////////////////////////////////////// private SEQUENCE sequence; private SEQUENCE controlSequence; private SEQUENCE reqSequence; private SEQUENCE cmsSequence; private SEQUENCE otherMsgSequence; /////////////////////////////////////////////////////////////////////// // Construction /////////////////////////////////////////////////////////////////////// /** * Constructs a PKIData from its components. * * @param controlSequence Sequence of TagggedAttribute. * @param reqSequence Sequence of TagggedRequest. * @param cmsSequence Sequence of TagggedContentInfo. * @param otherMsgSequence Sequence of OtherMsg. */ public PKIData(SEQUENCE controlSequence, SEQUENCE reqSequence, SEQUENCE cmsSequence, SEQUENCE otherMsgSequence) { sequence = new SEQUENCE(); this.controlSequence = controlSequence; sequence.addElement(controlSequence); this.reqSequence = reqSequence; sequence.addElement(reqSequence); this.cmsSequence = cmsSequence; sequence.addElement(cmsSequence); this.otherMsgSequence = otherMsgSequence; sequence.addElement(otherMsgSequence); } /////////////////////////////////////////////////////////////////////// // accessors /////////////////////////////////////////////////////////////////////// public SEQUENCE getControlSequence() { return controlSequence; } public SEQUENCE getReqSequence() { return reqSequence; } public SEQUENCE getCmsSequence() { return cmsSequence; } public SEQUENCE getOtherMsgSequence() { return otherMsgSequence; } /////////////////////////////////////////////////////////////////////// // DER encoding/decoding /////////////////////////////////////////////////////////////////////// static Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A template for decoding an PKIData from its BER encoding. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement(new SEQUENCE.OF_Template(TaggedAttribute.getTemplate()) ); seqt.addElement( new SEQUENCE.OF_Template(TaggedRequest.getTemplate()) ); seqt.addElement( new SEQUENCE.OF_Template(new ANY.Template()) ); seqt.addElement( new SEQUENCE.OF_Template(new ANY.Template()) ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); assert(seq.size() == 4); return new PKIData( (SEQUENCE) seq.elementAt(0), (SEQUENCE) seq.elementAt(1), (SEQUENCE) seq.elementAt(2), (SEQUENCE) seq.elementAt(3)); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/PendInfo.java000066400000000000000000000105221412550063600240700ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Date; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.GeneralizedTime; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * CMC PendInfo: *
 *   PendInfo ::= SEQUENCE {
 *       pendToken            OCTET STRING,
 *       pendTime             GeneralizedTime
 *   }
 * 
*/ public class PendInfo implements ASN1Value { /////////////////////////////////////////////////////////////////////// // Members /////////////////////////////////////////////////////////////////////// private SEQUENCE sequence; private OCTET_STRING pendToken; private GeneralizedTime pendTime; /////////////////////////////////////////////////////////////////////// // Construction /////////////////////////////////////////////////////////////////////// /** * Constructs a PendInfo from its components. * * @param pendToken the identifier. * @param pendTime the suggested time for the client to query the status. */ public PendInfo(OCTET_STRING pendToken, GeneralizedTime pendTime) { sequence = new SEQUENCE(); this.pendToken = pendToken; sequence.addElement(pendToken); this.pendTime = pendTime; sequence.addElement(pendTime); } /** * Constructs a PendInfo from requestId and date. * * @param reqId the request Id * @param date the suggested time for the client to query the status. */ public PendInfo(String reqId, Date date) { sequence = new SEQUENCE(); this.pendToken = new OCTET_STRING(reqId.getBytes()); sequence.addElement(new OCTET_STRING(reqId.getBytes())); this.pendTime = new GeneralizedTime(date); sequence.addElement(new GeneralizedTime(date)); } /////////////////////////////////////////////////////////////////////// // accessors /////////////////////////////////////////////////////////////////////// public GeneralizedTime getPendTime() { return pendTime; } public OCTET_STRING getPendToken() { return pendToken; } /////////////////////////////////////////////////////////////////////// // DER encoding/decoding /////////////////////////////////////////////////////////////////////// public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A template for decoding an PendInfo from its BER encoding. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( OCTET_STRING.getTemplate() ); seqt.addElement( GeneralizedTime.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); assert(seq.size() == 2); return new PendInfo( (OCTET_STRING) seq.elementAt(0), (GeneralizedTime) seq.elementAt(1)); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/PopLinkWitnessV2.java000066400000000000000000000134501412550063600255320ustar00rootroot00000000000000/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * 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 Services for Java. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.jss.pkix.cmc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; /** * CMC PopLinkWitnessV2: * per rfc 5272 *
 *     PopLinkWitnessV2 ::= SEQUENCE {
 *         keyGenAlgorithm     AlgorithmIdentifier,
 *         macAlgorithm       AlgorithmIdentifier,
 *         witness        OCTET STRING
 *     }
 * 
* * @author Christina Fu (cfu) */ public class PopLinkWitnessV2 implements ASN1Value { /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private AlgorithmIdentifier keyGenAlgorithm; private AlgorithmIdentifier macAlgorithm; private OCTET_STRING witness; private SEQUENCE sequence; // for DER encoding public AlgorithmIdentifier getKeyGenAlgorithm() { return keyGenAlgorithm; } public AlgorithmIdentifier getMacAlgorithm() { return macAlgorithm; } public OCTET_STRING getWitness() { return witness; } /////////////////////////////////////////////////////////////////////// // constructors /////////////////////////////////////////////////////////////////////// public PopLinkWitnessV2( AlgorithmIdentifier keyGenAlgorithm, AlgorithmIdentifier macAlgorithm, OCTET_STRING witness) { if( keyGenAlgorithm==null || macAlgorithm==null || witness==null ) { throw new IllegalArgumentException("PopLinkWitnessV2 constructor" +" parameter is null"); } this.keyGenAlgorithm = keyGenAlgorithm; this.macAlgorithm = macAlgorithm; this.witness = witness; sequence = new SEQUENCE(); sequence.addElement(keyGenAlgorithm); sequence.addElement(macAlgorithm); sequence.addElement(witness); } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template for decoding BER-encoded PopLinkWitnessV2 items. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( AlgorithmIdentifier.getTemplate() ); seqt.addElement( AlgorithmIdentifier.getTemplate() ); seqt.addElement( OCTET_STRING.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new PopLinkWitnessV2( (AlgorithmIdentifier) seq.elementAt(0), (AlgorithmIdentifier) seq.elementAt(1), (OCTET_STRING) seq.elementAt(2) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/ResponseBody.java000066400000000000000000000106131412550063600250030ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * A ResponseBody for CMC full enrollment request. * ResponseBody ::= SEQUENCE { * controlSequence SEQUENCE SIZE(0..MAX) OF TaggedAttribute, * cmsSequence SEQUENCE SIZE(0..MAX) OF TaggedContentInfo, * otherMsgSequence SEQUENCE SIZE(0..MAX) OF OtherMsg * } */ public class ResponseBody implements ASN1Value { /////////////////////////////////////////////////////////////////////// // Members /////////////////////////////////////////////////////////////////////// private SEQUENCE sequence; private SEQUENCE controlSequence; private SEQUENCE cmsSequence; private SEQUENCE otherMsgSequence; /////////////////////////////////////////////////////////////////////// // Construction /////////////////////////////////////////////////////////////////////// /** * Constructs a ResponseBody from its components. * * @param controlSequence Sequence of TagggedAttribute. * @param cmsSequence Sequence of TagggedContentInfo. * @param otherMsgSequence Sequence of OtherMsg. */ public ResponseBody(SEQUENCE controlSequence, SEQUENCE cmsSequence, SEQUENCE otherMsgSequence) { sequence = new SEQUENCE(); this.controlSequence = controlSequence; sequence.addElement(controlSequence); this.cmsSequence = cmsSequence; sequence.addElement(cmsSequence); this.otherMsgSequence = otherMsgSequence; sequence.addElement(otherMsgSequence); } /////////////////////////////////////////////////////////////////////// // accessors /////////////////////////////////////////////////////////////////////// public SEQUENCE getControlSequence() { return controlSequence; } public SEQUENCE getCmsSequence() { return cmsSequence; } public SEQUENCE getOtherMsgSequence() { return otherMsgSequence; } /////////////////////////////////////////////////////////////////////// // DER encoding/decoding /////////////////////////////////////////////////////////////////////// static Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A template for decoding an ResponseBody from its BER encoding. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement(new SEQUENCE.OF_Template(TaggedAttribute.getTemplate()) ); seqt.addElement(new SEQUENCE.OF_Template(ANY.getTemplate()) ); seqt.addElement(new SEQUENCE.OF_Template(ANY.getTemplate()) ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); assert(seq.size() == 3); return new ResponseBody( (SEQUENCE) seq.elementAt(0), (SEQUENCE) seq.elementAt(1), (SEQUENCE) seq.elementAt(2)); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/RevokeRequest.java000066400000000000000000000273541412550063600252050ustar00rootroot00000000000000/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * 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 Services for Java. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.jss.pkix.cmc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.ENUMERATED; import org.mozilla.jss.asn1.GeneralizedTime; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.asn1.UTF8String; /** * CMC RevokeRequest. *
 * RevokeRequest ::= SEQUENCE {
 *      issuerName      Name,
 *      serialNumber    INTEGER,
 *      reason          CRLReason,
 *      invalidityDate  GeneralizedTime OPTIONAL,
 *      passphrase    OCTET STRING OPTIONAL,
 *      comment         UTF8String OPTIONAL }
 * 
* * For maintenance and conformance reasons, this code is brought over * and mildly updated and renamed from cmmf/RevRequest during the process * of CMC update to rfc 5272 * @author Christina Fu (cfu) */ public class RevokeRequest implements ASN1Value { /////////////////////////////////////////////////////////////////////// // Constants /////////////////////////////////////////////////////////////////////// /** * A CRLReason, which can be used in the reason * field. */ public static final ENUMERATED unspecified = new ENUMERATED(0); /** * A CRLReason, which can be used in the reason * field. */ public static final ENUMERATED keyCompromise = new ENUMERATED(1); /** * A CRLReason, which can be used in the reason * field. */ public static final ENUMERATED cACompromise = new ENUMERATED(2); /** * A CRLReason, which can be used in the reason * field. */ public static final ENUMERATED affiliationChanged = new ENUMERATED(3); /** * A CRLReason, which can be used in the reason * field. */ public static final ENUMERATED superseded = new ENUMERATED(4); /** * A CRLReason, which can be used in the reason * field. */ public static final ENUMERATED cessationOfOperation = new ENUMERATED(5); /** * A CRLReason, which can be used in the reason * field. */ public static final ENUMERATED certificateHold = new ENUMERATED(6); /** * A CRLReason, which can be used in the reason * field. */ public static final ENUMERATED removeFromCRL = new ENUMERATED(8); /** * A CRLReason, which can be used in the reason * field. */ public static final ENUMERATED privilegeWithdrawn = new ENUMERATED(9); /** * A CRLReason, which can be used in the reason * field. */ public static final ENUMERATED aACompromise = new ENUMERATED(10); /////////////////////////////////////////////////////////////////////// // Members and member access /////////////////////////////////////////////////////////////////////// private ANY issuerName; private INTEGER serialNumber; private ENUMERATED reason; private GeneralizedTime invalidityDate; // may be null private OCTET_STRING passphrase; // may be null private UTF8String comment; // may be null private SEQUENCE sequence; /** * Returns the issuerName field as an ANY. */ public ANY getIssuerName() { return issuerName; } /** * Returns the serialNumber field. */ public INTEGER getSerialNumber() { return serialNumber; } /** * Returns the reason field, which should indicate the * reason for the revocation. The currently supported reasons are: *
     * CRLReason ::= ENUMERATED {
     *      unspecified             (0),
     *      keyCompromise           (1),
     *      cACompromise            (2),
     *      affiliationChanged      (3),
     *      superseded              (4),
     *      cessationOfOperation    (5),
     *      certificateHold         (6),
     *      removeFromCRL           (8),
     *      privilegeWithdrawn      (9),
     *      aACompromise            (10) }
     * 
* These are all defined as constants in this class. */ public ENUMERATED getReason() { return reason; } /** * Returns the invalidityDate field. Returns null * if the field is not present. */ public GeneralizedTime getInvalidityDate() { return invalidityDate; } /** * Returns the passphrase field. Returns * null if the field is not present. */ public OCTET_STRING getSharedSecret() { return passphrase; } /** * Returns the comment field. Returns null * if the field is not present. */ public UTF8String getComment() { return comment; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * Constructs a new RevokeRequest from its components, * omitting the invalidityDate field. * * @deprecated This constructor is obsolete now that * invalidityDate has been added to the class. * * @param issuerName The issuerName field. * @param serialNumber The serialNumber field. * @param reason The reason field. The constants defined * in this class may be used. * @param passphrase The passphrase field. This field is * optional, so null may be used. * @param comment The comment field. This field is optional, * so null may be used. */ @Deprecated public RevokeRequest(ANY issuerName, INTEGER serialNumber, ENUMERATED reason, OCTET_STRING passphrase, UTF8String comment) { this(issuerName, serialNumber, reason, null, passphrase, comment); } /** * Constructs a new RevokeRequest from its components. * * @param issuerName The issuerName field. * @param serialNumber The serialNumber field. * @param reason The reason field. The constants defined * in this class may be used. * @param invalidityDate The suggested value for the Invalidity Date * CRL extension. This field is optional, so null may be * used. * @param passphrase The passphrase field. This field is * optional, so null may be used. * @param comment The comment field. This field is optional, * so null may be used. */ public RevokeRequest(ANY issuerName, INTEGER serialNumber, ENUMERATED reason, GeneralizedTime invalidityDate, OCTET_STRING passphrase, UTF8String comment) { if( issuerName==null || serialNumber==null || reason==null ) { throw new IllegalArgumentException( "parameter to RevokeRequest constructor is null"); } sequence = new SEQUENCE(); this.issuerName = issuerName; sequence.addElement(issuerName); this.serialNumber = serialNumber; sequence.addElement(serialNumber); this.reason = reason; sequence.addElement(reason); this.invalidityDate = invalidityDate; sequence.addElement(invalidityDate); this.passphrase = passphrase; sequence.addElement(passphrase); this.comment = comment; sequence.addElement(comment); } /////////////////////////////////////////////////////////////////////// // encoding/decoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } /** * A Template class for decoding a RevokeRequest. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement(ANY.getTemplate()); seqt.addElement(INTEGER.getTemplate()); seqt.addElement(ENUMERATED.getTemplate()); seqt.addOptionalElement(GeneralizedTime.getTemplate()); seqt.addOptionalElement(OCTET_STRING.getTemplate()); seqt.addOptionalElement(UTF8String.getTemplate()); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new RevokeRequest( (ANY) seq.elementAt(0), (INTEGER) seq.elementAt(1), (ENUMERATED) seq.elementAt(2), (GeneralizedTime) seq.elementAt(3), (OCTET_STRING) seq.elementAt(4), (UTF8String) seq.elementAt(5) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/TaggedAttribute.java000066400000000000000000000113621412550063600254500ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.SET; import org.mozilla.jss.asn1.Tag; /** * A tagged attribute, which has the following ASN.1 * definition : *
 *   TaggedAttribute ::= SEQUENCE {
 *      bodyPartID         BodyPartId,
 *      attrType           OBJECT IDENTIFIER,
 *      attrValues         SET OF AttributeValue
 *   bodyIdMax INTEGER ::= 4294967295
 *
 *   BodyPartID ::= INTEGER(0..bodyIdMax)
 * 
*/ public class TaggedAttribute implements ASN1Value { public static final INTEGER BODYIDMAX = new INTEGER("4294967295"); /////////////////////////////////////////////////////////////////////// // Members /////////////////////////////////////////////////////////////////////// private SEQUENCE sequence; private INTEGER bodyPartID; private OBJECT_IDENTIFIER type; private SET values; /////////////////////////////////////////////////////////////////////// // Construction /////////////////////////////////////////////////////////////////////// public TaggedAttribute(INTEGER bodyPartID, OBJECT_IDENTIFIER type, SET values) { sequence = new SEQUENCE(); assert(bodyPartID.compareTo(BODYIDMAX) <= 0); this.bodyPartID = bodyPartID; sequence.addElement(bodyPartID); this.type = type; sequence.addElement(type); this.values = values; sequence.addElement(values); } public TaggedAttribute(INTEGER bodyPartID, OBJECT_IDENTIFIER type, ASN1Value value) { sequence = new SEQUENCE(); assert(bodyPartID.compareTo(BODYIDMAX) <= 0); this.bodyPartID = bodyPartID; sequence.addElement(bodyPartID); this.type = type; sequence.addElement(type); this.values = new SET(); values.addElement(value); sequence.addElement(values); } /////////////////////////////////////////////////////////////////////// // accessors /////////////////////////////////////////////////////////////////////// public INTEGER getBodyPartID() { return bodyPartID; } public OBJECT_IDENTIFIER getType() { return type; } /** * If this AVA was constructed, returns the SET of ASN1Values passed to the * constructor. If this Attribute was decoded with an Attribute.Template, * returns a SET of ANYs. */ public SET getValues() { return values; } /////////////////////////////////////////////////////////////////////// // DER encoding/decoding /////////////////////////////////////////////////////////////////////// public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicit, OutputStream ostream) throws IOException { sequence.encode(implicit, ostream); } public static Template getTemplate() { return templateInstance; } private static Template templateInstance = new Template(); /** * A Template for decoding an Attribute. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( INTEGER.getTemplate() ); seqt.addElement( new OBJECT_IDENTIFIER.Template() ); seqt.addElement( new SET.OF_Template(new ANY.Template())); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicit, InputStream istream) throws IOException, InvalidBERException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); // The template should have enforced this assert(seq.size() == 3); return new TaggedAttribute( (INTEGER) seq.elementAt(0), (OBJECT_IDENTIFIER) seq.elementAt(1), (SET) seq.elementAt(2)); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/TaggedCertificationRequest.java000066400000000000000000000103331412550063600276360ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.pkcs10.CertificationRequest; /** * CMC TaggedCertificationRequest: *
 *   TaggedCertificationRequest ::= SEQUENCE {
 *       bodyPartID            BodyPartID,
 *       certificationRequest  CertificationRequest
 *   }
 *   bodyIdMax INTEGER ::= 4294967295
 *
 *   BodyPartID ::= INTEGER(0..bodyIdMax)
 * 
*/ public class TaggedCertificationRequest implements ASN1Value { public static final INTEGER BODYIDMAX = new INTEGER("4294967295"); /////////////////////////////////////////////////////////////////////// // Members /////////////////////////////////////////////////////////////////////// private SEQUENCE sequence; private INTEGER bodyPartID; private CertificationRequest certificationRequest; /////////////////////////////////////////////////////////////////////// // Construction /////////////////////////////////////////////////////////////////////// /** * Constructs a TaggedCertificationRequest from its components. * * @param bodyPartID the identifier. * @param certificationRequest the pkcs10 request. */ public TaggedCertificationRequest(INTEGER bodyPartID, CertificationRequest certificationRequest) { sequence = new SEQUENCE(); assert(bodyPartID.compareTo(BODYIDMAX) <= 0); this.bodyPartID = bodyPartID; sequence.addElement(bodyPartID); this.certificationRequest = certificationRequest; sequence.addElement(certificationRequest); } /////////////////////////////////////////////////////////////////////// // accessors /////////////////////////////////////////////////////////////////////// public CertificationRequest getCertificationRequest() { return certificationRequest; } public INTEGER getBodyPartID() { return bodyPartID; } /////////////////////////////////////////////////////////////////////// // DER encoding/decoding /////////////////////////////////////////////////////////////////////// public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A template for decoding an TaggedCertificationRequest from its BER encoding. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( INTEGER.getTemplate() ); seqt.addElement( CertificationRequest.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); assert(seq.size() == 2); return new TaggedCertificationRequest( (INTEGER) seq.elementAt(0), (CertificationRequest) seq.elementAt(1)); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/TaggedContentInfo.java000066400000000000000000000076071412550063600257420ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmc; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.pkix.cms.ContentInfo; /** * CMC TaggedContentInfo. *
 * The definition of TaggedContentInfo comes from RFC 2797 Section 3.6.
 * TaggedContentInfo ::= SEQUENCE {
 *      bodyPartID      BodyPartID,
 *      contentInfo     ContentInfo}
 * 
*/ public class TaggedContentInfo implements ASN1Value { /////////////////////////////////////////////////////////////////////// // Members and member access /////////////////////////////////////////////////////////////////////// private INTEGER bodyPartID; private ContentInfo contentInfo; private SEQUENCE sequence; /** * Returns the bodyPartID field. */ public INTEGER getBodyPartID() { return bodyPartID; } /** * Returns the contentInfo field. */ public ContentInfo getContentInfo() { return contentInfo; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * Constructs a new TaggedContentInfo from its components. */ public TaggedContentInfo(INTEGER bodyPartID, ContentInfo contentInfo) { if (bodyPartID == null || contentInfo == null) { throw new IllegalArgumentException( "parameter to TaggedContentInfo constructor is null"); } sequence = new SEQUENCE(); this.bodyPartID = bodyPartID; sequence.addElement(bodyPartID); this.contentInfo = contentInfo; sequence.addElement(contentInfo); } /////////////////////////////////////////////////////////////////////// // encoding/decoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template for decoding a TaggedContentInfo. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement(INTEGER.getTemplate()); seqt.addElement(ContentInfo.getTemplate()); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new TaggedContentInfo((INTEGER)seq.elementAt(0), (ContentInfo)seq.elementAt(1)); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/TaggedRequest.java000066400000000000000000000172301412550063600251350ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmc; import org.mozilla.jss.asn1.*; import org.mozilla.jss.pkix.crmf.*; import java.io.*; /** * CMC TaggedRequest: *
 *   TaggedRequest ::= CHOICE { 
 *       tcr               [0] TaggedCertificationRequest, 
 *       crm               [1] CertReqMsg 
 *       orm               [2] SEQUENCE {
 *            bodyPartID            BodyPartID,
 *            requestMessageType    OBJECT IDENTIFIER,
 *            requestMessageValue   ANY DEFINED BY requestMessageType
 *       } // added for rfc 5272; defined in OtherReqMsg
 *   } 
 * 
*/ public class TaggedRequest implements ASN1Value { /** * The type of TaggedRequest. */ public static class Type { private Type() { } static Type PKCS10 = new Type(); static Type CRMF = new Type(); static Type OTHER = new Type(); } public static Type PKCS10 = Type.PKCS10; public static Type CRMF = Type.CRMF; public static Type OTHER = Type.OTHER; /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private Type type; private TaggedCertificationRequest tcr; // if type == PKCS10 private CertReqMsg crm; // if type == CRMF private OtherReqMsg orm; // if type == OTHER /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// // no default constructor public TaggedRequest() { } /** * Constructs a TaggedRequest from its components. * kept for backward compatibility for now * @param type The type of the request. * @param tcr Tagged pkcs10 request. * @param crm CRMF request. */ public TaggedRequest(Type type, TaggedCertificationRequest tcr, CertReqMsg crm) { this.type = type; this.tcr = tcr; this.crm = crm; } /** * Constructs a TaggedRequest from its components. * rfc 5272 * @param type The type of the request. * @param tcr Tagged pkcs10 request. * @param crm CRMF request. * @param orm OTHER request. */ public TaggedRequest(Type type, TaggedCertificationRequest tcr, CertReqMsg crm, OtherReqMsg orm) { this.type = type; this.tcr = tcr; this.crm = crm; this.orm = orm; } /////////////////////////////////////////////////////////////////////// // accessors /////////////////////////////////////////////////////////////////////// /** * Returns the type of TaggedRequest:
    *
  • PKCS10 *
  • CRMF *
  • OTHER *
*/ public Type getType() { return type; } /** * If type == PKCS10, returns the tcr field. Otherwise, * returns null. */ public TaggedCertificationRequest getTcr() { return tcr; } /** * If type == CRMF, returns the crm field. Otherwise, * returns null. */ public CertReqMsg getCrm() { return crm; } /** * If type == OTHER, returns the orm field. Otherwise, * returns null. */ public OtherReqMsg getOrm() { return orm; } /////////////////////////////////////////////////////////////////////// // DER decoding/encoding /////////////////////////////////////////////////////////////////////// @Override public Tag getTag() { if( type == PKCS10 ) { return Tag.get(0); } else if( type == CRMF ){ return Tag.get(1); } else { assert( type == OTHER ); return Tag.get(2); } } @Override public void encode(OutputStream ostream) throws IOException { if( type == PKCS10 ) { tcr.encode(Tag.get(0), ostream); // a CHOICE must be explicitly tagged //EXPLICIT e = new EXPLICIT( Tag.get(0), tcr ); //e.encode(ostream); } else if( type == CRMF ) { crm.encode(Tag.get(1), ostream); // a CHOICE must be explicitly tagged //EXPLICIT e = new EXPLICIT( Tag.get(1), crm ); //e.encode(ostream); } else { assert( type == OTHER ); orm.encode(Tag.get(2), ostream); // a CHOICE must be explicitly tagged //EXPLICIT e = new EXPLICIT( Tag.get(2), orm ); //e.encode(ostream); } } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { //Assert.notReached("A CHOICE cannot be implicitly tagged " +implicitTag.getNum()); //tagAt() of SET.java actually returns the underlying type encode(ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template for decoding a ProofOfPossession. */ public static class Template implements ASN1Template { private CHOICE.Template choicet; public Template() { choicet = new CHOICE.Template(); //EXPLICIT.Template et = new EXPLICIT.Template( // Tag.get(0), TaggedCertificationRequest.getTemplate() ); //choicet.addElement( et ); choicet.addElement( Tag.get(0), TaggedCertificationRequest.getTemplate() ); //et = new EXPLICIT.Template( // Tag.get(1), CertReqMsg.getTemplate() ); //choicet.addElement( et ); choicet.addElement( Tag.get(1), CertReqMsg.getTemplate() ); //et = new EXPLICIT.Template( // Tag.get(2), CertReqMsg.getTemplate() ); //choicet.addElement( et ); choicet.addElement( Tag.get(2), OtherReqMsg.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return choicet.tagMatch(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { CHOICE c = (CHOICE) choicet.decode(istream); if( c.getTag().equals(Tag.get(0)) ) { //EXPLICIT e = (EXPLICIT) c.getValue(); //return new TaggedRequest(PKCS10, // (TaggedCertificationRequest) // e.getContent(), null ); return new TaggedRequest(PKCS10, (TaggedCertificationRequest) c.getValue() , null); } if( c.getTag().equals(Tag.get(1)) ) { //EXPLICIT e = (EXPLICIT) c.getValue(); //return new TaggedRequest(CRMF, // (CertReqMsg) // e.getContent(), null ); return new TaggedRequest(CRMF, null, (CertReqMsg) c.getValue() , null); } else { assert( c.getTag().equals(Tag.get(2)) ); //EXPLICIT e = (EXPLICIT) c.getValue(); //return new TaggedRequest(OTHER, null, // (CertReqMsg) e.getContent() ); return new TaggedRequest(OTHER, null, null, (OtherReqMsg) c.getValue()); } } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { //Assert.notReached("A CHOICE cannot be implicitly tagged"); return decode(istream); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmc/package.html000066400000000000000000000004261412550063600240060ustar00rootroot00000000000000 Creating and interpeting CMC blobs. jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmmf/000077500000000000000000000000001412550063600217035ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmmf/CertOrEncCert.java000066400000000000000000000027011412550063600252100ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmmf; import org.mozilla.jss.asn1.*; import java.io.OutputStream; import java.io.IOException; import java.io.ByteArrayOutputStream; public class CertOrEncCert implements ASN1Value { private ANY certificate; byte[] encoding; /** * @exception InvalidBERException If the certificate is not a valid * BER-encoding. */ public CertOrEncCert(byte[] encodedCert) throws IOException, InvalidBERException { certificate = new ANY( new Tag(0), encodedCert ); ByteArrayOutputStream bos = new ByteArrayOutputStream(); certificate.encodeWithAlternateTag(new Tag(0), bos); encoding = bos.toByteArray(); } public static final Tag TAG = new Tag(0); @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { ostream.write(encoding); } /** * @param implicitTag This parameter is ignored, because a CHOICE * cannot have an implicit tag. */ @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { assert( implicitTag.equals(TAG) ); ostream.write(encoding); } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmmf/CertRepContent.java000066400000000000000000000112621412550063600254470ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmmf; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * A CMMF CertRepContent. *
 * CertRepContent ::= SEQUENCE {
 *      caPubs      [1] SEQUENCE SIZE (1..MAX) OF Certificate OPTIONAL,
 *      response    SEQUENCE of CertResponse }
 * 
* @see org.mozilla.jss.pkix.cmmf.CertResponse */ public class CertRepContent implements ASN1Value { private byte[][] caPubs; // may be null private SEQUENCE response; /** * Creates a new CertRepContent. * * @param caPubs An array of DER-encoded X.509 Certificates. It may be * null if the caPubs field is to be omitted. * @param response A SEQUENCE of CertResponse objects. * Must not be null. */ public CertRepContent(byte[][] caPubs, SEQUENCE response) { this.caPubs = caPubs; this.response = response; } /** * Creates a new CertRepContent. The responses can be * added later with addCertResponse. * * @param caPubs An array of DER-encoded X.509 Certificates, must not * be null and must have at least one element. */ public CertRepContent(byte[][] caPubs) { this.caPubs = caPubs; response = new SEQUENCE(); } /** * Creates a new CertRepContent * * @param response A SEQUENCE of CertResponse objects. * Must not be null. */ public CertRepContent(SEQUENCE response) { this.caPubs = null; this.response = response; } /** * Adds another CertResponse. */ public void addCertResponse(CertResponse resp) { response.addElement(resp); } /** * Returns the caPubs field, which is an array of * DER-encoded X.509 Certificates. May return null if the * field is not present. */ public byte[][] getCaPubs() { return caPubs; } /** * Returns the response field, which is a SEQUENCE * of CertResponse */ public SEQUENCE getResponse() { return response; } public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { SEQUENCE encoding = new SEQUENCE(); // create sequence of certificates if(caPubs != null) { SEQUENCE certs = new SEQUENCE(); for(int i = 0; i < caPubs.length; i++) { certs.addElement( new ANY( SEQUENCE.TAG, caPubs[i] ) ); } encoding.addElement( new Tag(1), certs ); } encoding.addElement( response ); encoding.encode(implicitTag, ostream); } public static void main(String argv[]) { if(argv.length != 2) { System.out.println("Usage: CertRepContent "); System.out.println("certfile should contain a DER-encoded X.509 "+ "certificate"); System.exit(-1); } try (FileInputStream certfile = new FileInputStream(argv[0]); FileOutputStream fos = new FileOutputStream(argv[1])) { byte[][] certs = new byte[2][]; certs[0] = new byte[ certfile.available() ]; certfile.read(certs[0]); certs[1] = certs[0]; PKIStatusInfo status = new PKIStatusInfo(PKIStatusInfo.rejection, PKIStatusInfo.badRequest | PKIStatusInfo.badTime ); status.addFreeText("And your mother dresses you funny"); status.addFreeText("so there"); CertifiedKeyPair ckp = new CertifiedKeyPair( new CertOrEncCert( certs[0] ) ); CertResponse resp = new CertResponse( new INTEGER(54), status, ckp); CertRepContent content = new CertRepContent(certs); content.addCertResponse(resp); content.encode(fos); System.out.println("Success!"); } catch( Exception e ) { e.printStackTrace(); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmmf/CertResponse.java000066400000000000000000000041541412550063600251660ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmmf; import java.io.IOException; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; public class CertResponse implements ASN1Value { private INTEGER certReqId; private PKIStatusInfo status; private CertifiedKeyPair certifiedKeyPair; public CertResponse(INTEGER certReqId, PKIStatusInfo status) { this.certReqId = certReqId; this.status = status; } public CertResponse(INTEGER certReqId, PKIStatusInfo status, CertifiedKeyPair certifiedKeyPair) { this(certReqId, status); this.certifiedKeyPair = certifiedKeyPair; } public INTEGER getCertReqId() { return certReqId; } public PKIStatusInfo getPKIStatusInfo() { return status; } /** * Returns true if the certifiedKeyPair field is present. */ public boolean hasCertifiedKeyPair() { return (certifiedKeyPair != null); } /** * Returns the optional certified key pair. Should only be called if * the certifiedKeyPair field is present. */ public CertifiedKeyPair getCertifiedKeyPair() { assert(certifiedKeyPair!=null); return certifiedKeyPair; } public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); seq.addElement( certReqId ); seq.addElement( status ); if( certifiedKeyPair != null ) { seq.addElement( certifiedKeyPair ); } seq.encode(implicitTag, ostream); } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmmf/CertifiedKeyPair.java000066400000000000000000000017601412550063600257350ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmmf; import org.mozilla.jss.asn1.*; import java.io.OutputStream; import java.io.IOException; public class CertifiedKeyPair implements ASN1Value { private CertOrEncCert certOrEncCert; public CertifiedKeyPair(CertOrEncCert certOrEncCert) { this.certOrEncCert = certOrEncCert; } public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); seq.addElement( certOrEncCert ); seq.encode(implicitTag, ostream); } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmmf/GetCRL.java000066400000000000000000000146011412550063600236300ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmmf; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BIT_STRING; import org.mozilla.jss.asn1.GeneralizedTime; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * CMMF GetCRL. *
 * GetCRL ::= SEQUENCE {
 *      issuerName      Name,
 *      cRLName         GeneralName OPTIONAL,
 *      time            GeneralizedTime OPTIONAL,
 *      reasons         ReasonFlags OPTIONAL }
 * 
*/ public class GetCRL implements ASN1Value { /////////////////////////////////////////////////////////////////////// // constants /////////////////////////////////////////////////////////////////////// /** * A bit position in a ReasonFlags bit string. */ public static final int unused = 0; /** * A bit position in a ReasonFlags bit string. */ public static final int keyCompromise = 1; /** * A bit position in a ReasonFlags bit string. */ public static final int cACompromise = 2; /** * A bit position in a ReasonFlags bit string. */ public static final int affiliationChanged = 3; /** * A bit position in a ReasonFlags bit string. */ public static final int superseded = 4; /** * A bit position in a ReasonFlags bit string. */ public static final int cessationOfOperation = 5; /** * A bit position in a ReasonFlags bit string. */ public static final int certificateHold = 6; /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private ANY issuerName; private ANY cRLName; // may be null private GeneralizedTime time; // may be null private BIT_STRING reasons; // may be null private SEQUENCE sequence; /** * Returns the issuerName field. */ public ANY getIssuerName() { return issuerName; } /** * Returns the cRLName field, which may be null. */ public ANY getCRLName() { return cRLName; } /** * Returns the time field, which may be null. */ public GeneralizedTime getTime() { return time; } /** * Returns the reasons field, which may be null. */ public BIT_STRING getReasons() { return reasons; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * Constructs a GetCRL from its components. * * @param issuerName The issuer name of the CRL. This should be an ASN.1 * Name. * @param cRLName The name of the CRL, which may be null. * This should be an ASN.1 GeneralName. * @param time The time of the CRL, which may be null. * @param reasons Can be used to specify from among CRLs partitioned * by revocation reason. The BIT_STRING can be created from a * Java BitSet. The positions in the BitSet should be set or cleared * using the constants provided in this class. */ public GetCRL( ANY issuerName, ANY cRLName, GeneralizedTime time, BIT_STRING reasons ) { if( issuerName == null ) { throw new IllegalArgumentException( "issuerName parameter to GetCRL constructor is null"); } sequence = new SEQUENCE(); this.issuerName = issuerName; sequence.addElement(issuerName); this.cRLName = cRLName; sequence.addElement(cRLName); this.time = time; sequence.addElement(time); // Remove trailing zeroes in this bit string because it contains // flags. this.reasons = reasons; reasons.setRemoveTrailingZeroes(true); sequence.addElement(reasons); } /////////////////////////////////////////////////////////////////////// // encoding / decoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template for decoding a GetCRL. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( ANY.getTemplate() ); seqt.addOptionalElement( ANY.getTemplate() ); seqt.addOptionalElement( GeneralizedTime.getTemplate() ); seqt.addOptionalElement( BIT_STRING.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new GetCRL( (ANY) seq.elementAt(0), (ANY) seq.elementAt(1), (GeneralizedTime) seq.elementAt(2), (BIT_STRING) seq.elementAt(3) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmmf/IssuerAndSubject.java000066400000000000000000000100561412550063600257650ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmmf; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * CMMF IssuerAndSubject. *
 * IssuerAndSubject ::= SEQUENCE {
 *      issuer          Name,
 *      subject         Name,
 *      certReqId       INTEGER OPTIONAL }
 * 
*/ public class IssuerAndSubject implements ASN1Value { /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private ANY issuer; private ANY subject; private INTEGER certReqId; // may be null private SEQUENCE sequence; /** * Returns the issuer field. */ public ANY getIssuer() { return issuer; } /** * Returns the subject field. */ public ANY getSubject() { return subject; } /** * Returns the certReqId field, which may be null. */ public INTEGER getCertReqId() { return certReqId; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// public IssuerAndSubject(ANY issuer, ANY subject, INTEGER certReqId) { if( issuer==null || subject==null ) { throw new IllegalArgumentException( "parameter to IssuerAndSubject constructor is null"); } sequence = new SEQUENCE(); this.issuer = issuer; sequence.addElement(issuer); this.subject = subject; sequence.addElement(subject); this.certReqId = certReqId; sequence.addElement(certReqId); } /////////////////////////////////////////////////////////////////////// // encoding/decoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template for decoding an IssuerAndSubject. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( ANY.getTemplate() ); seqt.addElement( ANY.getTemplate() ); seqt.addOptionalElement( INTEGER.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new IssuerAndSubject( (ANY) seq.elementAt(0), (ANY) seq.elementAt(1), (INTEGER) seq.elementAt(2) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmmf/PKIStatusInfo.java000066400000000000000000000135101412550063600252110ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmmf; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.BitSet; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BIT_STRING; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.asn1.UTF8String; public class PKIStatusInfo implements ASN1Value { private INTEGER status; private SEQUENCE statusString; private int failInfo; // bitwise AND private boolean hasFailInfo; // PKIStatus constants public static final int granted = 0; public static final int grantedWithMods = 1; public static final int rejection = 2; public static final int waiting = 3; public static final int revocationWarning = 4; public static final int revocationNotification = 5; public static final int keyUpdateWarning = 6; // PKIFailureInfo constants // The bit string encoded in four bytes, big-endian, bit 0 is MSB. public static final int badAlg = 0x80000000; public static final int badMessageCheck = 0x40000000; public static final int badRequest = 0x20000000; public static final int badTime = 0x10000000; public static final int badCertId = 0x08000000; public static final int badDataFormat = 0x04000000; public static final int wrongAuthority = 0x02000000; public static final int incorrectData = 0x01000000; public static final int missingTimeStamp = 0x00800000; /** * @param status A PKIStatus constant. * @param failInfo The bitwise AND of the PKIFailureInfo constants. */ public PKIStatusInfo(int status, int failInfo) { this.status = new INTEGER(status); statusString = new SEQUENCE(); this.failInfo = failInfo; hasFailInfo = true; } /** * Create a PKIStatusInfo with no failure info. * @param status A PKIStatus constant. */ public PKIStatusInfo(int status) { this.status = new INTEGER(status); statusString = new SEQUENCE(); hasFailInfo = false; } /** * Sets the statusString field. May be null, since this * field is optional. */ public void setStatusString(SEQUENCE statusString) { this.statusString = statusString; } /** * Adds a string to the statusString SEQUENCE. */ public void addFreeText(String s) { try { statusString.addElement( new UTF8String(s) ); } catch( java.io.CharConversionException e ) { throw new RuntimeException("Error encoding to UTF8: " + e.getMessage(), e); } } /** * Adds a UTF8String to the statusString SEQUENCE. */ public void addFreeText(UTF8String s) { statusString.addElement( s ); } public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); seq.addElement(status); if( statusString.size() > 0 ) { seq.addElement( statusString ); } if(hasFailInfo) { // convert failInfo to BIT_STRING byte[] bytes = new byte[2]; bytes[0] = (byte) ((failInfo & 0xff000000) >>> 24); bytes[1] = (byte) ((failInfo & 0x00ff0000) >>> 16); int padCount = 7; // 7 unused bits BIT_STRING bs = new BIT_STRING(bytes, padCount); bs.setRemoveTrailingZeroes(true); seq.addElement( bs ); } seq.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( INTEGER.getTemplate() ); seqt.addOptionalElement( new SEQUENCE.OF_Template(UTF8String.getTemplate())); seqt.addOptionalElement( BIT_STRING.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { PKIStatusInfo psi; SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); BIT_STRING failInfo = (BIT_STRING) seq.elementAt(2); if( failInfo == null ) { psi = new PKIStatusInfo(((INTEGER)seq.elementAt(0)).intValue()); } else { BitSet bs = failInfo.toBitSet(); int failinfo = 0; for(int i = 0, bit = 0x80000000; bit > 0; i++, bit >>>= 1 ) { if( bs.get(i) ) { failinfo |= bit; } } psi = new PKIStatusInfo(((INTEGER)seq.elementAt(0)).intValue(), failinfo); } psi.setStatusString( (SEQUENCE) seq.elementAt(1) ); return psi; } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmmf/RevRepContent.java000066400000000000000000000122131412550063600253030ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmmf; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.pkix.crmf.CertId; /** * CMMF RevRepContent. *
 * RevRepContent ::= SEQUENCE {
 *    status          SEQUENCE SIZE (1..MAX) OF PKIStatusInfo,
 *      -- in same order as was sent in RevReqContent
 *    revCerts        [0] SEQUENCE SIZE (1..MAX) OF CertId OPTIONAL,
 *      -- IDs for which revocation was requested (same order as status)
 *    crls            [1] SEQUENCE SIZE (1..MAX) OF CertificateList OPTIONAL
 *      -- the resulting CRLs (there may be more than one) }
 * 
*/ public class RevRepContent implements ASN1Value { /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private SEQUENCE status; private SEQUENCE revCerts; // may be null private SEQUENCE crls; // may be null private SEQUENCE sequence; // for encoding /** * The status field, which is a SEQUENCE * of PKIStatusInfo. * * @see org.mozilla.jss.pkix.cmmf.PKIStatusInfo */ public SEQUENCE getStatus() { return status; } /** * The revCerts field, which is a SEQUENCE * of CertId. Returns null if this * field is not present. * * @see org.mozilla.jss.pkix.crmf.CertId */ public SEQUENCE getRevCerts() { return revCerts; } /** * The crls field, which is a SEQUENCE of * ANY. Returns null if this field * is not present. */ public SEQUENCE getCrls() { return crls; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * Creates a new RevRepContent from its components. * * @param status A SEQUENCE of PKIStatusInfo. * @param revCerts A SEQUENCE of CertId. This * field is optional, so null may be used. * @param crls A SEQUENCE of ANY. This field * is optional, so null may be used. * @see org.mozilla.jss.pkix.cmmf.PKIStatusInfo */ public RevRepContent(SEQUENCE status, SEQUENCE revCerts, SEQUENCE crls) { sequence = new SEQUENCE(); this.status = status; sequence.addElement(status); this.revCerts = revCerts; sequence.addElement(Tag.get(0), revCerts); this.crls = crls; sequence.addElement(Tag.get(1), crls); } /////////////////////////////////////////////////////////////////////// // encoding/decoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } /** * A Template for decoding a RevRepContent. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( new SEQUENCE.OF_Template( PKIStatusInfo.getTemplate() ) ); seqt.addOptionalElement( new SEQUENCE.OF_Template( CertId.getTemplate() ) ); seqt.addOptionalElement( new SEQUENCE.OF_Template( ANY.getTemplate() ) ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new RevRepContent( (SEQUENCE) seq.elementAt(0), (SEQUENCE) seq.elementAt(1), (SEQUENCE) seq.elementAt(2) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmmf/RevRequest.java000066400000000000000000000251331412550063600246570ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cmmf; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.ENUMERATED; import org.mozilla.jss.asn1.GeneralizedTime; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.asn1.UTF8String; /** * CMMF RevRequest. *
 * RevRequest ::= SEQUENCE {
 *      issuerName      Name,
 *      serialNumber    INTEGER,
 *      reason          CRLReason,
 *      invalidityDate  GeneralizedTime OPTIONAL,
 *      sharedSecret    OCTET STRING OPTIONAL,
 *      comment         UTF8String OPTIONAL }
 * 
* For maintenance and conformance reasons, this code has been brought * over and renamed to cmc/RevokeRequest during the CMC update to rfc 5272. * All new code should use cmc/RevokeRequest instead */ public class RevRequest implements ASN1Value { /////////////////////////////////////////////////////////////////////// // Constants /////////////////////////////////////////////////////////////////////// /** * A CRLReason, which can be used in the reason * field. */ public static final ENUMERATED unspecified = new ENUMERATED(0); /** * A CRLReason, which can be used in the reason * field. */ public static final ENUMERATED keyCompromise = new ENUMERATED(1); /** * A CRLReason, which can be used in the reason * field. */ public static final ENUMERATED cACompromise = new ENUMERATED(2); /** * A CRLReason, which can be used in the reason * field. */ public static final ENUMERATED affiliationChanged = new ENUMERATED(3); /** * A CRLReason, which can be used in the reason * field. */ public static final ENUMERATED superseded = new ENUMERATED(4); /** * A CRLReason, which can be used in the reason * field. */ public static final ENUMERATED cessationOfOperation = new ENUMERATED(5); /** * A CRLReason, which can be used in the reason * field. */ public static final ENUMERATED certificateHold = new ENUMERATED(6); /** * A CRLReason, which can be used in the reason * field. */ public static final ENUMERATED removeFromCRL = new ENUMERATED(8); /** * A CRLReason, which can be used in the reason * field. */ public static final ENUMERATED privilegeWithdrawn = new ENUMERATED(9); /** * A CRLReason, which can be used in the reason * field. */ public static final ENUMERATED aACompromise = new ENUMERATED(10); /////////////////////////////////////////////////////////////////////// // Members and member access /////////////////////////////////////////////////////////////////////// private ANY issuerName; private INTEGER serialNumber; private ENUMERATED reason; private GeneralizedTime invalidityDate; // may be null private OCTET_STRING sharedSecret; // may be null private UTF8String comment; // may be null private SEQUENCE sequence; /** * Returns the issuerName field as an ANY. */ public ANY getIssuerName() { return issuerName; } /** * Returns the serialNumber field. */ public INTEGER getSerialNumber() { return serialNumber; } /** * Returns the reason field, which should indicate the * reason for the revocation. The currently supported reasons are: *
     * CRLReason ::= ENUMERATED {
     *      unspecified             (0),
     *      keyCompromise           (1),
     *      cACompromise            (2),
     *      affiliationChanged      (3),
     *      superseded              (4),
     *      cessationOfOperation    (5),
     *      certificateHold         (6),
     *      removeFromCRL           (8),
     *      privilegeWithdrawn      (9),
     *      aACompromise            (10) }
     * 
* These are all defined as constants in this class. */ public ENUMERATED getReason() { return reason; } /** * Returns the invalidityDate field. Returns null * if the field is not present. */ public GeneralizedTime getInvalidityDate() { return invalidityDate; } /** * Returns the passphrase field. Returns * null if the field is not present. * @deprecated The passphrase field has been renamed * sharedSecret. Call getSharedSecret instead. */ @Deprecated public OCTET_STRING getPassphrase() { return sharedSecret; } /** * Returns the sharedSecret field. Returns * null if the field is not present. */ public OCTET_STRING getSharedSecret() { return sharedSecret; } /** * Returns the comment field. Returns null * if the field is not present. */ public UTF8String getComment() { return comment; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * Constructs a new RevRequest from its components, * omitting the invalidityDate field. * * @deprecated This constructor is obsolete now that * invalidityDate has been added to the class. * * @param issuerName The issuerName field. * @param serialNumber The serialNumber field. * @param reason The reason field. The constants defined * in this class may be used. * @param sharedSecret The sharedSecret field. This field is * optional, so null may be used. * @param comment The comment field. This field is optional, * so null may be used. */ @Deprecated public RevRequest(ANY issuerName, INTEGER serialNumber, ENUMERATED reason, OCTET_STRING sharedSecret, UTF8String comment) { this(issuerName, serialNumber, reason, null, sharedSecret, comment); } /** * Constructs a new RevRequest from its components. * * @param issuerName The issuerName field. * @param serialNumber The serialNumber field. * @param reason The reason field. The constants defined * in this class may be used. * @param invalidityDate The suggested value for the Invalidity Date * CRL extension. This field is optional, so null may be * used. * @param sharedSecret The sharedSecret field. This field is * optional, so null may be used. * @param comment The comment field. This field is optional, * so null may be used. */ public RevRequest(ANY issuerName, INTEGER serialNumber, ENUMERATED reason, GeneralizedTime invalidityDate, OCTET_STRING sharedSecret, UTF8String comment) { if( issuerName==null || serialNumber==null || reason==null ) { throw new IllegalArgumentException( "parameter to RevRequest constructor is null"); } sequence = new SEQUENCE(); this.issuerName = issuerName; sequence.addElement(issuerName); this.serialNumber = serialNumber; sequence.addElement(serialNumber); this.reason = reason; sequence.addElement(reason); this.invalidityDate = invalidityDate; sequence.addElement(invalidityDate); this.sharedSecret = sharedSecret; sequence.addElement(sharedSecret); this.comment = comment; sequence.addElement(comment); } /////////////////////////////////////////////////////////////////////// // encoding/decoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } /** * A Template class for decoding a RevRequest. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement(ANY.getTemplate()); seqt.addElement(INTEGER.getTemplate()); seqt.addElement(ENUMERATED.getTemplate()); seqt.addOptionalElement(GeneralizedTime.getTemplate()); seqt.addOptionalElement(OCTET_STRING.getTemplate()); seqt.addOptionalElement(UTF8String.getTemplate()); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new RevRequest( (ANY) seq.elementAt(0), (INTEGER) seq.elementAt(1), (ENUMERATED) seq.elementAt(2), (GeneralizedTime) seq.elementAt(3), (OCTET_STRING) seq.elementAt(4), (UTF8String) seq.elementAt(5) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cmmf/package.html000066400000000000000000000004121412550063600241610ustar00rootroot00000000000000 The PKIX CMMF protocol. jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cms/000077500000000000000000000000001412550063600215435ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cms/ContentInfo.java000066400000000000000000000177441412550063600246510ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cms; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.EXPLICIT; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * A PKCS #7 ContentInfo structure. */ public class ContentInfo implements ASN1Value { public static final Tag TAG = SEQUENCE.TAG; // XXX is this right? public static OBJECT_IDENTIFIER DATA = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 1 }); public static OBJECT_IDENTIFIER SIGNED_DATA = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 2 }); public static OBJECT_IDENTIFIER ENVELOPED_DATA = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 3 }); public static OBJECT_IDENTIFIER SIGNED_AND_ENVELOPED_DATA = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 4 }); public static OBJECT_IDENTIFIER DIGESTED_DATA = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 5 }); public static OBJECT_IDENTIFIER ENCRYPTED_DATA = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549, 1, 7, 6 }); private OBJECT_IDENTIFIER contentType; private ANY content; private SEQUENCE sequence = new SEQUENCE(); /** * Creates a ContentInfo with the given type and content. * * @param contentType The contentType of the ContentInfo. * @param content The content of the ContentInfo. May be null * to signify that the optional content field is not present. */ public ContentInfo(OBJECT_IDENTIFIER contentType, ASN1Value content) { this.contentType = contentType; sequence.addElement(contentType); if (content != null) { if( content instanceof ANY ) { this.content = (ANY) content; } else { // convert content to ANY try { this.content = (ANY) ASN1Util.decode(ANY.getTemplate(), ASN1Util.encode(content) ); } catch(InvalidBERException e) { throw new RuntimeException("Unable to convert "+ "ASN1Value to ANY: " + e.getMessage(), e); } } sequence.addElement(new EXPLICIT(new Tag(0),content) ); } } /** * Creates a ContentInfo of type data. */ public ContentInfo(byte[] data) { this( DATA, new OCTET_STRING(data) ); } /** * Creates a ContentInfo of type signedData. */ public ContentInfo(SignedData sd) { this( SIGNED_DATA, sd); } /** * Creates a ContentInfo of type envelopedData. */ public ContentInfo(EnvelopedData ed) { this( ENVELOPED_DATA, ed ); } /** * Creates a ContentInfo of type signedAndEnvelopedData. */ public ContentInfo(SignedAndEnvelopedData sed) { this( SIGNED_AND_ENVELOPED_DATA, sed ); } /** * Creates a ContentInfo of type digestedData. */ public ContentInfo(DigestedData dd) { this( DIGESTED_DATA, dd ); } /** * Creates a ContentInfo of type encryptedData. */ public ContentInfo(EncryptedData ed) { this( ENCRYPTED_DATA, ed ); } /** * Returns the contentType field, which determines what kind of content * is contained in this ContentInfo. It will usually be one of the six * predefined types, but may also be a user-defined type. */ public OBJECT_IDENTIFIER getContentType() { return contentType; } /** * Returns true if the content field is present. */ public boolean hasContent() { return (content != null); } /** * Returns the content, interpreted based on its type. If there is no * content, null is returned. *

If the contentType is * one of the six standard types, the returned object will be of that * type. For example, if the ContentInfo has contentType signedData, * a SignedData object will be returned. If the contentType is data, * an OCTET_STRING will be returned. *

If the contentType is not one of the six standard types, * the returned object will be an ANY. */ public ASN1Value getInterpretedContent() throws InvalidBERException { if(contentType.equals(DATA)) { return content.decodeWith( new OCTET_STRING.Template() ); } else if( contentType.equals(SIGNED_DATA) ) { return content.decodeWith( new SignedData.Template() ); } else if( contentType.equals(ENVELOPED_DATA) ) { return content.decodeWith( new EnvelopedData.Template()); } else if( contentType.equals(SIGNED_AND_ENVELOPED_DATA) ) { return content.decodeWith( new SignedAndEnvelopedData.Template() ); } else if( contentType.equals(DIGESTED_DATA) ) { return content.decodeWith( new DigestedData.Template() ); } else if( contentType.equals(ENCRYPTED_DATA) ) { return content.decodeWith( new EncryptedData.Template()); } else { // unknown type return content; } } /** * Returns the content encoded as an ANY. If there is no content, * null is returned. */ public ANY getContent() { return content; } @Override public void encode(OutputStream ostream) throws IOException { encode(getTag(),ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag,ostream); } @Override public Tag getTag() { return ContentInfo.TAG; } /** * Returns a singleton instance of a decoding template for ContentInfo. */ public static Template getTemplate() { return templateInstance; } private static Template templateInstance = new Template(); /** * A template for decoding a ContentInfo blob * */ public static class Template implements ASN1Template { @Override public boolean tagMatch(Tag tag) { return (tag.equals(ContentInfo.TAG)); } private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement(new OBJECT_IDENTIFIER.Template()); seqt.addOptionalElement( new EXPLICIT.Template( new Tag(0), new ANY.Template() )); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(ContentInfo.TAG,istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream ) throws IOException, InvalidBERException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); assert(seq.size() == 2); ASN1Value content; if( seq.elementAt(1) == null ) { content = null; } else { content = ((EXPLICIT)seq.elementAt(1)).getContent(); } return new ContentInfo( (OBJECT_IDENTIFIER) seq.elementAt(0), content ); } } // end of template } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cms/DigestInfo.java000066400000000000000000000072721412550063600244510ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cms; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; public class DigestInfo implements ASN1Value { private AlgorithmIdentifier digestAlgorithm; private OCTET_STRING digest; private SEQUENCE sequence; public DigestInfo(AlgorithmIdentifier digestAlgorithm, OCTET_STRING digest){ if( digestAlgorithm==null || digest==null ) { throw new IllegalArgumentException(); } sequence = new SEQUENCE(); this.digestAlgorithm = digestAlgorithm; sequence.addElement(digestAlgorithm); this.digest = digest; sequence.addElement(digest); } public AlgorithmIdentifier getDigestAlgorithm() { return digestAlgorithm; } public OCTET_STRING getDigest() { return digest; } private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public boolean equals(Object obj) { if( obj==null || !(obj instanceof DigestInfo)) { return false; } DigestInfo di = (DigestInfo)obj; return byteArraysAreSame(di.digest.toByteArray(), digest.toByteArray()); } /** * Compares two non-null byte arrays. Returns true if they are identical, * false otherwise. */ private static boolean byteArraysAreSame(byte[] left, byte[] right) { assert(left!=null && right!=null); if( left.length != right.length ) { return false; } for(int i = 0 ; i < left.length ; i++ ) { if( left[i] != right[i] ) { return false; } } return true; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A class for decoding the BER encoding of a DigestInfo. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( AlgorithmIdentifier.getTemplate()); seqt.addElement( OCTET_STRING.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream ostream) throws InvalidBERException, IOException { return decode(TAG, ostream); } @Override public ASN1Value decode(Tag implicitTag, InputStream ostream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, ostream); return new DigestInfo( (AlgorithmIdentifier) seq.elementAt(0), (OCTET_STRING) seq.elementAt(1) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cms/DigestedData.java000066400000000000000000000101471412550063600247330ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cms; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; public class DigestedData implements ASN1Value { /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private INTEGER version; private AlgorithmIdentifier digestAlgorithm; private ContentInfo contentInfo; private OCTET_STRING digest; private SEQUENCE sequence; // for DER encoding public INTEGER getVersion() { return version; } public AlgorithmIdentifier getDigestAlgorithm() { return digestAlgorithm; } public ContentInfo getContentInfo() { return contentInfo; } public OCTET_STRING getDigest() { return digest; } /////////////////////////////////////////////////////////////////////// // constructors /////////////////////////////////////////////////////////////////////// public DigestedData(INTEGER version, AlgorithmIdentifier digestAlgorithm, ContentInfo contentInfo, OCTET_STRING digest) { if( version==null || digestAlgorithm==null || contentInfo==null || digest==null ) { throw new IllegalArgumentException("DigestedData constructor" +" parameter is null"); } this.version = version; this.digestAlgorithm = digestAlgorithm; this.contentInfo = contentInfo; this.digest = digest; sequence = new SEQUENCE(); sequence.addElement(version); sequence.addElement(digestAlgorithm); sequence.addElement(contentInfo); sequence.addElement(digest); } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } /** * A Template for decoding BER-encoded DigestData items. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( INTEGER.getTemplate() ); seqt.addElement( AlgorithmIdentifier.getTemplate() ); seqt.addElement( ContentInfo.getTemplate() ); seqt.addElement( OCTET_STRING.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new DigestedData( (INTEGER) seq.elementAt(0), (AlgorithmIdentifier) seq.elementAt(1), (ContentInfo) seq.elementAt(2), (OCTET_STRING) seq.elementAt(3) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cms/EncapsulatedContentInfo.java000066400000000000000000000111531412550063600271660ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cms; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.EXPLICIT; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * A CMS EncapsulatedContentInfo structure. */ public class EncapsulatedContentInfo implements ASN1Value { public static final Tag TAG = SEQUENCE.TAG; // XXX is this right? private OBJECT_IDENTIFIER contentType; private OCTET_STRING content; private SEQUENCE sequence = new SEQUENCE(); /** * Creates a EncapsulatedContentInfo with the given type and content. * * @param contentType The contentType of the EncapsulatedContentInfo. * @param content The content of the EncapsulatedContentInfo. May be null * to signify that the optional content field is not present. */ public EncapsulatedContentInfo(OBJECT_IDENTIFIER contentType, ASN1Value content) { this.contentType = contentType; sequence.addElement(contentType); if (content != null) { if( content instanceof OCTET_STRING) { this.content = (OCTET_STRING) content; } else { // convert content to OCTET_STRING this.content = new OCTET_STRING( ASN1Util.encode(content) ); } sequence.addElement(new EXPLICIT(new Tag(0), this.content) ); } } /** * Returns the contentType field, which determines what kind of content * is contained in this EncapsulatedContentInfo. */ public OBJECT_IDENTIFIER getContentType() { return contentType; } /** * Returns true if the content field is present. */ public boolean hasContent() { return (content != null); } /** * Returns the content encoded as an OCTET_STRING. If there is no content, * null is returned. */ public OCTET_STRING getContent() { return content; } @Override public void encode(OutputStream ostream) throws IOException { encode(getTag(),ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag,ostream); } @Override public Tag getTag() { return EncapsulatedContentInfo.TAG; } /** * Returns a singleton instance of a decoding template for EncapsulatedContentInfo. */ public static Template getTemplate() { return templateInstance; } private static Template templateInstance = new Template(); /** * A template for decoding a EncapsulatedContentInfo blob * */ public static class Template implements ASN1Template { @Override public boolean tagMatch(Tag tag) { return (tag.equals(EncapsulatedContentInfo.TAG)); } private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement(new OBJECT_IDENTIFIER.Template()); seqt.addOptionalElement( new EXPLICIT.Template( new Tag(0), new OCTET_STRING.Template() )); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(EncapsulatedContentInfo.TAG,istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream ) throws IOException, InvalidBERException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); assert(seq.size() == 2); ASN1Value content; if( seq.elementAt(1) == null ) { content = null; } else { content = ((EXPLICIT)seq.elementAt(1)).getContent(); } return new EncapsulatedContentInfo( (OBJECT_IDENTIFIER) seq.elementAt(0), content ); } } // end of template } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cms/EncryptedContentInfo.java000066400000000000000000000314171412550063600265200ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cms; import java.io.CharConversionException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.BadPaddingException; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.EXPLICIT; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.crypto.Cipher; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.EncryptionAlgorithm; import org.mozilla.jss.crypto.IVParameterSpec; import org.mozilla.jss.crypto.IllegalBlockSizeException; import org.mozilla.jss.crypto.KeyGenAlgorithm; import org.mozilla.jss.crypto.KeyGenerator; import org.mozilla.jss.crypto.PBEAlgorithm; import org.mozilla.jss.crypto.PBEKeyGenParams; import org.mozilla.jss.crypto.SymmetricKey; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; import org.mozilla.jss.pkix.primitive.PBEParameter; import org.mozilla.jss.util.Password; /** * The PKCS #7 type EncryptedContentInfo, which encapsulates * encrypted data. */ public class EncryptedContentInfo implements ASN1Value { /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private OBJECT_IDENTIFIER contentType; private AlgorithmIdentifier contentEncryptionAlgorithm; private OCTET_STRING encryptedContent; // may be null private SEQUENCE sequence = new SEQUENCE(); public OBJECT_IDENTIFIER getContentType() { return contentType; } public AlgorithmIdentifier getContentEncryptionAlgorithm() { return contentEncryptionAlgorithm; } public OCTET_STRING getEncryptedContent() { return encryptedContent; } public boolean hasEncryptedContent() { return (encryptedContent!=null); } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * Create a EnvelopedData ASN1 object. */ public EncryptedContentInfo( OBJECT_IDENTIFIER contentType, AlgorithmIdentifier contentEncryptionAlgorithm, OCTET_STRING encryptedContent) { this(contentType, contentEncryptionAlgorithm, encryptedContent, false); } public EncryptedContentInfo( OBJECT_IDENTIFIER contentType, AlgorithmIdentifier contentEncryptionAlgorithm, OCTET_STRING encryptedContent, boolean createHackedCRSCompatibleECI) { this.contentType = contentType; this.contentEncryptionAlgorithm = contentEncryptionAlgorithm; this.encryptedContent = encryptedContent; sequence.addElement(contentType); sequence.addElement(contentEncryptionAlgorithm); if(encryptedContent != null) { if (createHackedCRSCompatibleECI) { sequence.addElement(new EXPLICIT(new Tag(0), encryptedContent)); } else { sequence.addElement(new Tag(0), encryptedContent); } } } public static EncryptedContentInfo createCRSCompatibleEncryptedContentInfo(OBJECT_IDENTIFIER contentType, AlgorithmIdentifier contentEncryptionAlgorithm, OCTET_STRING encryptedContent) { return new EncryptedContentInfo(contentType, contentEncryptionAlgorithm, encryptedContent, true); } /////////////////////////////////////////////////////////////////////// // Crypto shortcuts /////////////////////////////////////////////////////////////////////// /** * Creates a new EncryptedContentInfo, where the data is encrypted * with a password-based key. * * @param keyGenAlg The algorithm for generating a symmetric key from * a password, salt, and iteration count. * @param password The password to use in generating the key. * @param salt The salt to use in generating the key. * @param iterationCount The number of hashing iterations to perform * while generating the key. * @param charToByteConverter The mechanism for converting the characters * in the password into bytes. If null, the default mechanism * will be used, which is UTF8. * @param toBeEncrypted The bytes to be encrypted and stored in the * EncryptedContentInfo. Before they are encrypted, they will be * padded using PKCS padding. */ public static EncryptedContentInfo createPBE(PBEAlgorithm keyGenAlg, Password password, byte[] salt, int iterationCount, KeyGenerator.CharToByteConverter charToByteConverter, byte[] toBeEncrypted) throws NotInitializedException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException, TokenException, CharConversionException { try { // check key gen algorithm if( ! (keyGenAlg instanceof PBEAlgorithm) ) { throw new NoSuchAlgorithmException("Key generation algorithm"+ " is not a PBE algorithm"); } PBEAlgorithm pbeAlg = keyGenAlg; CryptoManager cman = CryptoManager.getInstance(); // generate key CryptoToken token = cman.getInternalCryptoToken(); KeyGenerator kg = token.getKeyGenerator( keyGenAlg ); PBEKeyGenParams pbekgParams = new PBEKeyGenParams( password, salt, iterationCount); if( charToByteConverter != null ) { kg.setCharToByteConverter( charToByteConverter ); } kg.initialize(pbekgParams); SymmetricKey key = kg.generate(); // generate IV EncryptionAlgorithm encAlg = pbeAlg.getEncryptionAlg(); AlgorithmParameterSpec params=null; Class [] paramClasses = encAlg.getParameterClasses(); for (int i = 0; i < paramClasses.length; i ++) { if ( paramClasses[i].equals( IVParameterSpec.class ) ) { params = new IVParameterSpec( kg.generatePBE_IV() ); break; } } // perform encryption Cipher cipher = token.getCipherContext( encAlg ); cipher.initEncrypt( key, params ); byte[] encrypted = cipher.doFinal( Cipher.pad( toBeEncrypted, encAlg.getBlockSize()) ); // make encryption algorithm identifier PBEParameter pbeParam = new PBEParameter( salt, iterationCount ); AlgorithmIdentifier encAlgID = new AlgorithmIdentifier( keyGenAlg.toOID(), pbeParam); // create EncryptedContentInfo EncryptedContentInfo encCI = new EncryptedContentInfo( ContentInfo.DATA, encAlgID, new OCTET_STRING(encrypted) ); return encCI; } catch( IllegalBlockSizeException e ) { throw new RuntimeException("IllegalBlockSizeException in EncryptedContentInfo" +".createPBE: " + e.getMessage(), e); } catch( BadPaddingException e ) { throw new RuntimeException("BadPaddingException in EncryptedContentInfo" +".createPBE: " + e.getMessage(), e); } } /** * Decrypts the content of an EncryptedContentInfo encrypted with a * PBE key. * * @param pass The password to use in generating the PBE decryption key. * @param charToByteConverter The converter for converting the password * characters into bytes. May be null to use the default. * @return The decrypted contents of the EncryptedContentInfo. The contents * are first unpadded using the PKCS padding mechanism. */ public byte[] decrypt(Password pass, KeyGenerator.CharToByteConverter charToByteConverter) throws IllegalStateException,NotInitializedException, NoSuchAlgorithmException, InvalidBERException, IOException, InvalidKeyException, InvalidAlgorithmParameterException, TokenException, IllegalBlockSizeException, BadPaddingException { if( encryptedContent == null ) { return null; } // get the key gen parameters AlgorithmIdentifier algid = contentEncryptionAlgorithm; KeyGenAlgorithm kgAlg = KeyGenAlgorithm.fromOID( algid.getOID() ); if( !(kgAlg instanceof PBEAlgorithm) ) { throw new NoSuchAlgorithmException("KeyGenAlgorithm is not a"+ " PBE algorithm"); } ASN1Value params = algid.getParameters(); if( params == null ) { throw new InvalidAlgorithmParameterException( "PBE algorithms require parameters"); } PBEParameter pbeParams; if( params instanceof PBEParameter) { pbeParams = (PBEParameter) params; } else { byte[] encodedParams = ASN1Util.encode(params); pbeParams = (PBEParameter) ASN1Util.decode( PBEParameter.getTemplate(), encodedParams ); } PBEKeyGenParams kgp = new PBEKeyGenParams(pass, pbeParams.getSalt(), pbeParams.getIterations() ); // compute the key and IV CryptoToken token = CryptoManager.getInstance().getInternalCryptoToken(); KeyGenerator kg = token.getKeyGenerator( kgAlg ); if( charToByteConverter != null ) { kg.setCharToByteConverter( charToByteConverter ); } kg.initialize( kgp ); SymmetricKey key = kg.generate(); // compute algorithm parameters EncryptionAlgorithm encAlg = ((PBEAlgorithm)kgAlg).getEncryptionAlg(); AlgorithmParameterSpec algParams = null; Class [] paramClasses = encAlg.getParameterClasses(); for (int i = 0; i < paramClasses.length; i ++) { if ( paramClasses[i].equals( javax.crypto.spec.IvParameterSpec.class ) ) { algParams = new IVParameterSpec( kg.generatePBE_IV() ); break; } } // perform the decryption Cipher cipher = token.getCipherContext( encAlg ); cipher.initDecrypt(key, algParams); return Cipher.unPad(cipher.doFinal( encryptedContent.toByteArray() )); } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(getTag(),ostream); } @Override public void encode(Tag tag, OutputStream ostream) throws IOException { sequence.encode(tag,ostream); } public static Template getTemplate() { return templateInstance; } private static final Template templateInstance = new Template(); /** * A template file for decoding a EnvelopedData blob * */ public static class Template implements ASN1Template { @Override public boolean tagMatch(Tag tag) { return (tag.equals(EncryptedContentInfo.TAG)); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG,istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { SEQUENCE.Template seqt = new SEQUENCE.Template(); seqt.addElement(new OBJECT_IDENTIFIER.Template()); seqt.addElement(new AlgorithmIdentifier.Template()); seqt.addOptionalElement(new Tag(0), new OCTET_STRING.Template()); SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); assert(seq.size() ==3); return new EncryptedContentInfo( (OBJECT_IDENTIFIER) seq.elementAt(0), (AlgorithmIdentifier) seq.elementAt(1), (OCTET_STRING) seq.elementAt(2) ); } } // end of template } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cms/EncryptedData.java000066400000000000000000000103541412550063600251400ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cms; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * The PKCS #7 structure EncryptedData. */ public class EncryptedData implements ASN1Value { /////////////////////////////////////////////////////////////////////// // Members /////////////////////////////////////////////////////////////////////// private INTEGER version; private EncryptedContentInfo encryptedContentInfo; private SEQUENCE sequence; /** * The default version number. This should always be used unless * you really know what you are doing. */ public static final INTEGER DEFAULT_VERSION = new INTEGER(0); /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * Creates a new EncryptedData. * * @param version Should usually be DEFAULT_VERSION unless you are being * very clever. */ public EncryptedData( INTEGER version, EncryptedContentInfo encryptedContentInfo ) { if( version == null || encryptedContentInfo == null ) { throw new IllegalArgumentException("null parameter"); } sequence = new SEQUENCE(); this.version = version; sequence.addElement(version); this.encryptedContentInfo = encryptedContentInfo; sequence.addElement(encryptedContentInfo); } /** * Creates an EncryptedData with the default version. */ public EncryptedData( EncryptedContentInfo encryptedContentInfo ) { this( DEFAULT_VERSION, encryptedContentInfo ); } /////////////////////////////////////////////////////////////////////// // Accessor Methods /////////////////////////////////////////////////////////////////////// public INTEGER getVersion() { return version; } public EncryptedContentInfo getEncryptedContentInfo() { return encryptedContentInfo; } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } public static Template getTemplate() { return templateInstance; } private static final Template templateInstance = new Template(); /** * A Template for decoding EncryptedData items. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( INTEGER.getTemplate() ); seqt.addElement( EncryptedContentInfo.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new EncryptedData( (INTEGER) seq.elementAt(0), (EncryptedContentInfo) seq.elementAt(1) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cms/EnvelopedData.java000066400000000000000000000063721412550063600251310ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cms; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.SET; import org.mozilla.jss.asn1.Tag; public class EnvelopedData implements ASN1Value { public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } private INTEGER version; private SET recipientInfos; private EncryptedContentInfo encryptedContentInfo; private SEQUENCE sequence = new SEQUENCE(); public INTEGER getVersion() { return version; } public SET getRecipientInfos() { return recipientInfos; } public EncryptedContentInfo getEncryptedContentInfo() { return encryptedContentInfo; } /** * Create a EnvelopedData ASN1 object. */ public EnvelopedData( INTEGER version, SET recipientInfos, EncryptedContentInfo encryptedContentInfo) { this.version = version; this.recipientInfos = recipientInfos; this.encryptedContentInfo = encryptedContentInfo; sequence.addElement(version); sequence.addElement(recipientInfos); sequence.addElement(encryptedContentInfo); } @Override public void encode(OutputStream ostream) throws IOException { encode(getTag(),ostream); } @Override public void encode(Tag tag, OutputStream ostream) throws IOException { sequence.encode(tag,ostream); } /** * A template file for decoding a EnvelopedData blob * */ public static class Template implements ASN1Template { public Tag getTag() { return EnvelopedData.TAG; } @Override public boolean tagMatch(Tag tag) { return (tag.equals(EnvelopedData.TAG)); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(getTag(),istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { SEQUENCE.Template seqt = new SEQUENCE.Template(); seqt.addElement(new INTEGER.Template()); seqt.addElement(new SET.OF_Template(new RecipientInfo.Template())); seqt.addElement(new EncryptedContentInfo.Template()); SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); assert(seq.size() ==3); return new EnvelopedData( (INTEGER) seq.elementAt(0), (SET) seq.elementAt(1), (EncryptedContentInfo) seq.elementAt(2) ); } } // end of template } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cms/IssuerAndSerialNumber.java000066400000000000000000000075141412550063600266230ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cms; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.pkix.primitive.Name; /** * An issuer name and serial number, used to uniquely identify a certificate. */ public class IssuerAndSerialNumber implements ASN1Value { /////////////////////////////////////////////////////////////////////// // Members /////////////////////////////////////////////////////////////////////// private Name issuer; private INTEGER serialNumber; private SEQUENCE sequence; /////////////////////////////////////////////////////////////////////// // Construction /////////////////////////////////////////////////////////////////////// /** * Constructs an IssuerAndSerialNumber from its components. * * @param issuer Must not be null. * @param serialNumber must not be null. */ public IssuerAndSerialNumber(Name issuer, INTEGER serialNumber) { if(issuer==null || serialNumber==null) { throw new IllegalArgumentException(); } sequence = new SEQUENCE(); this.issuer = issuer; sequence.addElement(issuer); this.serialNumber = serialNumber; sequence.addElement(serialNumber); } /////////////////////////////////////////////////////////////////////// // accessors /////////////////////////////////////////////////////////////////////// public Name getIssuer() { return issuer; } public INTEGER getSerialNumber() { return serialNumber; } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// static Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } /** * Returns a singleton template instance. */ public static Template getTemplate() { return templateInstance; } private static Template templateInstance = new Template(); /** * A template for decoding an IssuerAndSerialNumber from its BER encoding. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( Name.getTemplate() ); seqt.addElement( INTEGER.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); assert(seq.size() == 2); return new IssuerAndSerialNumber( (Name) seq.elementAt(0), (INTEGER) seq.elementAt(1) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cms/RecipientInfo.java000066400000000000000000000100121412550063600251360ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cms; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; public class RecipientInfo implements ASN1Value { public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } private INTEGER version; private IssuerAndSerialNumber issuerAndSerialNumber; private AlgorithmIdentifier keyEncryptionAlgorithmID; private OCTET_STRING encryptedKey; private SEQUENCE sequence = new SEQUENCE(); public INTEGER getVersion() { return version; } public IssuerAndSerialNumber getissuerAndSerialNumber() { return issuerAndSerialNumber; } public AlgorithmIdentifier getKeyEncryptionAlgorithmID() { return keyEncryptionAlgorithmID; } public OCTET_STRING getEncryptedKey() { return encryptedKey; } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * Create a RecipientInfo ASN1 object. */ public RecipientInfo( INTEGER version, IssuerAndSerialNumber issuerAndSerialNumber, AlgorithmIdentifier keyEncryptionAlgorithmID, OCTET_STRING encryptedKey) { assert(issuerAndSerialNumber != null); assert(keyEncryptionAlgorithmID != null); assert(encryptedKey != null); this.version = version; this.issuerAndSerialNumber = issuerAndSerialNumber; this.keyEncryptionAlgorithmID = keyEncryptionAlgorithmID; this.encryptedKey = encryptedKey; sequence.addElement(version); sequence.addElement(issuerAndSerialNumber); sequence.addElement(keyEncryptionAlgorithmID); sequence.addElement(encryptedKey); } @Override public void encode(OutputStream ostream) throws IOException { encode(getTag(),ostream); } @Override public void encode(Tag tag, OutputStream ostream) throws IOException { sequence.encode(tag,ostream); } /** * A template file for decoding a RecipientInfo blob * */ public static class Template implements ASN1Template { public Tag getTag() { return RecipientInfo.TAG; } @Override public boolean tagMatch(Tag tag) { return (tag.equals(RecipientInfo.TAG)); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(getTag(),istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { SEQUENCE.Template seqt = new SEQUENCE.Template(); seqt.addElement(new INTEGER.Template()); seqt.addElement(new IssuerAndSerialNumber.Template()); seqt.addElement(new AlgorithmIdentifier.Template()); seqt.addElement(new OCTET_STRING.Template()); SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); assert(seq.size() ==4); return new RecipientInfo( (INTEGER) seq.elementAt(0), (IssuerAndSerialNumber) seq.elementAt(1), (AlgorithmIdentifier) seq.elementAt(2), (OCTET_STRING) seq.elementAt(3) ); } } // end of template } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cms/SignedAndEnvelopedData.java000066400000000000000000000141641412550063600267040ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cms; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.SET; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; public class SignedAndEnvelopedData implements ASN1Value { /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private INTEGER version; private SET recipientInfos; private SET digestAlgorithms; private EncryptedContentInfo encryptedContentInfo; private SET certificates; // may be null private SET crls; // may be null private SET signerInfos; private SEQUENCE sequence; // for encoding /** * Returns the version number. The current version is 1. */ public INTEGER getVersion() { return version; } /** * Returns a SET of RecipientInfo. */ public SET getRecipientInfos() { return recipientInfos; } /** * Returns a SET of AlgorithmIdentifier. */ public SET getDigestAlgorithms() { return digestAlgorithms; } /** * Returns the encrypted content. */ public EncryptedContentInfo getEncryptedContentInfo() { return encryptedContentInfo; } /** * Returns a SET of ANYs. May return null if the * certificates field is not present. */ public SET getCertificates() { return certificates; } /** * Returns a SET of ANYs. May return null if the crls * field is not present. */ public SET getCrls() { return crls; } /** * Returns a SET of SignerInfo. */ public SET getSignerInfos() { return signerInfos; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// public SignedAndEnvelopedData( INTEGER version, SET recipientInfos, SET digestAlgorithms, EncryptedContentInfo encryptedContentInfo, SET certificates, SET crls, SET signerInfos) { if( version==null || recipientInfos==null || digestAlgorithms==null || encryptedContentInfo==null || signerInfos==null ) { throw new IllegalArgumentException( "SignedAndEnvelopedData constructor parameter is null"); } this.version = version; this.recipientInfos = recipientInfos; this.digestAlgorithms = digestAlgorithms; this.encryptedContentInfo = encryptedContentInfo; this.certificates = certificates; this.crls = crls; this.signerInfos = signerInfos; sequence = new SEQUENCE(); sequence.addElement(version); sequence.addElement(recipientInfos); sequence.addElement(digestAlgorithms); sequence.addElement(encryptedContentInfo); if( certificates!=null ) { sequence.addElement(certificates); } if( crls!=null ) { sequence.addElement(crls); } sequence.addElement( signerInfos ); } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } /** * A Template class for decoding BER-encoded SignedAndEnvelopedData items. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement(INTEGER.getTemplate()); seqt.addElement(new SET.OF_Template(RecipientInfo.getTemplate())); seqt.addElement(new SET.OF_Template( AlgorithmIdentifier.getTemplate()) ); seqt.addElement(EncryptedContentInfo.getTemplate()); seqt.addOptionalElement(new Tag(0), new SET.OF_Template(ANY.getTemplate())); seqt.addOptionalElement(new Tag(1), new SET.OF_Template(ANY.getTemplate())); seqt.addElement(new SET.OF_Template(SignerInfo.getTemplate())); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new SignedAndEnvelopedData( (INTEGER) seq.elementAt(0), (SET) seq.elementAt(1), (SET) seq.elementAt(2), (EncryptedContentInfo) seq.elementAt(3), (SET) seq.elementAt(4), (SET) seq.elementAt(5), (SET) seq.elementAt(6) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cms/SignedData.java000066400000000000000000000327031412550063600244160ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cms; import java.io.*; import org.mozilla.jss.asn1.*; import org.mozilla.jss.pkix.primitive.*; import org.mozilla.jss.pkix.cert.Certificate; /* CUT THIS??? *

Although all the normal functionality of a SignedData is supported * with high-level methods, there is a low-level API for setting the * individual fields of the structure. Using these calls is an unsupported * way of accomplishing unforeseen tasks. If you have reason to use these * methods, please notify the authors in case it is something that should * be added to the high-level interface. * */ /** * A CMS SignedData structure. *

The certificates field should only contain X.509 certificates. * PKCS #6 extended certificates will fail to decode properly. * @author stevep * @author nicolson * @author mzhao */ public class SignedData implements ASN1Value { /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Members /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// private INTEGER version; private SET digestAlgorithms; private EncapsulatedContentInfo contentInfo; private SET certificates; // [0] optional, may be null private SET crls; // [1] optional, may be null private SET signerInfos; // This class implements version 3 of the spec. private static final INTEGER VERSION = new INTEGER(3); /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Accessor methods /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// private static void verifyNotNull(Object obj) { if( obj == null ) { throw new IllegalArgumentException(); } } /** * Returns the version of this SignedData. The current version of the * spec is version 3. */ public INTEGER getVersion() { return version; } /** * Low-level function to set the version. * @param version Must not be null. public void setVersion(INTEGER version) { verifyNotNull(version); this.version = version; } */ /** * Returns the digest algorithms used by the signers to digest the * signed content. There may be more than one, if different signers * use different digesting algorithms. */ public SET getDigestAlgorithmIdentifiers() { return digestAlgorithms; } /** * Low-level function to set the digest algorithm identifiers. * @param digestAlgIds Must not be null. public void setDigestAlgorithmIdentifiers(SET digestAlgIds) { verifyNotNull(digestAlgIds); this.digestAlgorithms = digestAlgIds; } */ /** * Returns the EncapsulatedContentInfo containing the signed content. The simple * case is for the content to be of type data, although any * content type can be signed. */ public EncapsulatedContentInfo getContentInfo() { return contentInfo; } /** * Low-level function to set the EncapsulatedcontentInfo. * @param ci Must not be null. public void setContentInfo(EncapsulatedContentInfo ci) { verifyNotNull(ci); this.contentInfo = ci; } */ /** * Returns the certificates field, which is a SET of * X.509 certificates (org.mozilla.jss.pkix.cert.Certificate). * PKCS #6 Extended Certificates are not supported by this implementation. * Returns null if this optional field is not present. * */ public SET getCertificates() { return certificates; } /** * Low-level function to set the certificates. * @param certs May be null to signify that the certificates * field is not present. public void setCertificates(SET certs) { this.certificates = certs; } */ /** * Returns true if the certificates field is present. */ public boolean hasCertificates() { return (certificates!=null); } /** * Returns the crls field, which contains a SET of certificate * revocation lists represented by ANYs (org.mozilla.jss.asn1.ANY). * */ public SET getCrls() { return crls; } /** * Low-level function to set the crls. * @param certs May be null to signify that the crls * field is not present. public void setCrls(SET crls) { this.crls = crls; } */ /** * Returns true if the crls field is present. */ public boolean hasCrls() { return (crls != null); } /** * Returns the signerInfos field, which is a SET of * org.mozilla.jss.pkix.cms.SignerInfo. */ public SET getSignerInfos() { return signerInfos; } /** * Low-level function to set the SignerInfos. * @param signerInfos Must not be null. public void setSignerInfos(SET signerInfos) { verifyNotNull(sis); this.signerInfos = signerInfos; } */ /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// /** * Low-level constructor that merely initializes all fields to null. private SignedData() {} */ /** * Create a SignedData ASN1 object. Both certificates and CRLs * are optional. If you pass in a null for either value, that * parameter will not get written in the sequence. * * @param digestAlgorithms A SET of zero or more * algorithm identifiers. The purpose of this item is to list * the digest algorithms used by the various signers to digest * the signed content. This field will also be updated by * the addSigner method. If all the signers are added * with addSigner, it is not necessary to list * the digest algorithms here. *

If null is passed in, the * digestAlgorithms field will be initialized * with an empty SET. * @param contentInfo The content that is being signed. This parameter * may not be null. However, the content * field of the contentInfo may be omitted, in which case the * signatures contained in the SignerInfo structures * are presumed to be on externally-supplied data. * @param certificates A SET of org.mozilla.jss.pkix.cert.Certificate, * the certificates * containing the public keys used to sign the content. It may * also contain elements of the CA chain extending from the leaf * certificates. It is not necessary to include the CA chain, or * indeed to include any certificates, if the certificates are * expected to already be possessed by the recipient. The recipient * can use the issuer and serial number in the SignerInfo structure * to search for the necessary certificates. If this parameter is * null, the certificates field will be * omitted. * @param crls A SET of ASN1Values, which should encode to the ASN1 type * CertificateRevocationList. This implementation does * not interpret CRLs. If this parameter is null, * the crls field will be omitted. * @param signerInfos SignerInfo structures containing signatures * of the content. Additional signerInfos can be added with * the addSigner method. If this parameter is * null, the field will be initialized with an * empty SET. */ public SignedData( SET digestAlgorithms, EncapsulatedContentInfo contentInfo, SET certificates, SET crls, SET signerInfos) { version = VERSION; if(digestAlgorithms == null ) { this.digestAlgorithms = new SET(); } else { this.digestAlgorithms = digestAlgorithms; } verifyNotNull(contentInfo); this.contentInfo = contentInfo; // certificates may be null this.certificates = certificates; // crls may be null this.crls = crls; if(signerInfos == null) { this.signerInfos = new SET(); } else { this.signerInfos = signerInfos; } } /** * Constructor for creating a SignedData from its encoding. */ SignedData( INTEGER version, SET digestAlgorithms, EncapsulatedContentInfo contentInfo, SET certificates, SET crls, SET signerInfos ) { verifyNotNull(version); this.version = version; verifyNotNull(digestAlgorithms); this.digestAlgorithms = digestAlgorithms; verifyNotNull(contentInfo); this.contentInfo = contentInfo; // certificates may be null this.certificates = certificates; // crls may be null this.crls = crls; verifyNotNull(signerInfos); this.signerInfos = signerInfos; } /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Cryptographic functions /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(getTag(),ostream); } @Override public void encode(Tag tag, OutputStream ostream) throws IOException { SEQUENCE sequence = new SEQUENCE(); sequence.addElement(version); sequence.addElement(digestAlgorithms); sequence.addElement(contentInfo); if( certificates != null ) { sequence.addElement( new Tag(0), certificates ); } if( crls != null ) { sequence.addElement( new Tag(1), crls ); } sequence.addElement(signerInfos); sequence.encode(tag,ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A template file for decoding a SignedData blob * */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); // version seqt.addElement(INTEGER.getTemplate()); // digestAlgorithms seqt.addElement(new SET.OF_Template( AlgorithmIdentifier.getTemplate())); // content info seqt.addElement(EncapsulatedContentInfo.getTemplate()); // [0] IMPLICIT certificates OPTIONAL seqt.addOptionalElement( new Tag(0), new SET.OF_Template(Certificate.getTemplate())); // [1] IMPLICIT CertificateRevocationLists OPTIONAL seqt.addOptionalElement( new Tag(1), new SET.OF_Template(ANY.getTemplate())); // signerInfos seqt.addElement(new SET.OF_Template(SignerInfo.getTemplate())); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); assert(seq.size() == 6); return new SignedData( (INTEGER) seq.elementAt(0), (SET) seq.elementAt(1), (EncapsulatedContentInfo) seq.elementAt(2), (SET) seq.elementAt(3), (SET) seq.elementAt(4), (SET) seq.elementAt(5) ); } } // end of template } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cms/SignerIdentifier.java000066400000000000000000000141301412550063600256370ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cms; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.CHOICE; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * CMS SignerIdentifier: *

 * SignerIdentifier ::= CHOICE {
 *      issuerAndSerialNumber IssuerAndSerialNumber,
 *      subjectKeyIdentifier [0] SubjectKeyIdentifier }
 * 
*/ public class SignerIdentifier implements ASN1Value { /** * The type of SignerIdentifier. */ public static class Type { private Type() { } static Type ISSUER_AND_SERIALNUMBER = new Type(); static Type SUBJECT_KEY_IDENTIFIER = new Type(); } public static Type ISSUER_AND_SERIALNUMBER = Type.ISSUER_AND_SERIALNUMBER; public static Type SUBJECT_KEY_IDENTIFIER = Type.SUBJECT_KEY_IDENTIFIER; /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private Type type; private IssuerAndSerialNumber issuerAndSerialNumber = null; // if type == ISSUER_AND_SERIALNUMBER private OCTET_STRING subjectKeyIdentifier = null; // if type == SUBJECT_KEY_IDENTIFIER /** * Returns the type of SignerIdentifier:
    *
  • ISSUER_AND_SERIALNUMBER *
  • SUBJECT_KEY_IDENTIFIER *
*/ public Type getType() { return type; } /** * If type == ISSUER_AND_SERIALNUMBER, returns the IssuerAndSerialNumber * field. Otherwise, returns null. */ public IssuerAndSerialNumber getIssuerAndSerialNumber() { return issuerAndSerialNumber; } /** * If type == SUBJECT_KEY_IDENTIFIER, returns the SubjectKeyIdentifier * field. Otherwise, returns null. */ public OCTET_STRING getSubjectKeyIdentifier() { return subjectKeyIdentifier; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// public SignerIdentifier(Type type, IssuerAndSerialNumber issuerAndSerialNumber, OCTET_STRING subjectKeyIdentifier) { this.type = type; this.issuerAndSerialNumber = issuerAndSerialNumber; this.subjectKeyIdentifier = subjectKeyIdentifier; } /** * Creates a new SignerIdentifier with the given IssuerAndSerialNumber field. */ public static SignerIdentifier createIssuerAndSerialNumber(IssuerAndSerialNumber ias) { return new SignerIdentifier( ISSUER_AND_SERIALNUMBER, ias, null ); } /** * Creates a new SignerIdentifier with the given SubjectKeyIdentifier field. */ public static SignerIdentifier createSubjectKeyIdentifier(OCTET_STRING ski) { return new SignerIdentifier(SUBJECT_KEY_IDENTIFIER , null, ski ); } /////////////////////////////////////////////////////////////////////// // decoding/encoding /////////////////////////////////////////////////////////////////////// @Override public Tag getTag() { if( type == SUBJECT_KEY_IDENTIFIER ) { return Tag.get(0); } else { assert( type == ISSUER_AND_SERIALNUMBER ); return IssuerAndSerialNumber.TAG; } } @Override public void encode(OutputStream ostream) throws IOException { if( type == SUBJECT_KEY_IDENTIFIER ) { // a CHOICE must be explicitly tagged //EXPLICIT e = new EXPLICIT( Tag.get(0), subjectKeyIdentifier ); //e.encode(ostream); subjectKeyIdentifier.encode(Tag.get(0), ostream); } else { assert( type == ISSUER_AND_SERIALNUMBER ); issuerAndSerialNumber.encode(ostream); } } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { //Assert.notReached("A CHOICE cannot be implicitly tagged"); encode(ostream); } public static Template getTemplate() { return templateInstance; } private static Template templateInstance = new Template(); /** * A Template for decoding a SignerIdentifier. */ public static class Template implements ASN1Template { private CHOICE.Template choicet; public Template() { choicet = new CHOICE.Template(); //EXPLICIT.Template et = new EXPLICIT.Template( // Tag.get(0), OCTET_STRING.getTemplate() ); //choicet.addElement( et ); choicet.addElement( Tag.get(0), OCTET_STRING.getTemplate() ); choicet.addElement(IssuerAndSerialNumber.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return choicet.tagMatch(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { CHOICE c = (CHOICE) choicet.decode(istream); if( c.getTag() == SEQUENCE.TAG ) { return createIssuerAndSerialNumber( (IssuerAndSerialNumber) c.getValue() ); } else { assert( c.getTag().equals(Tag.get(0)) ); //EXPLICIT e = (EXPLICIT) c.getValue(); //ASN1Value dski = e.getContent(); //OCTET_STRING ski = (OCTET_STRING) e.getContent(); OCTET_STRING ski = (OCTET_STRING) c.getValue(); return createSubjectKeyIdentifier(ski); } } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { //Assert.notReached("A CHOICE cannot be implicitly tagged"); return decode(istream); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cms/SignerInfo.java000066400000000000000000000717411412550063600244630ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.cms; import java.io.*; import org.mozilla.jss.asn1.*; import org.mozilla.jss.pkix.primitive.*; import org.mozilla.jss.crypto.*; import java.security.InvalidKeyException; import java.security.SignatureException; import java.security.NoSuchAlgorithmException; import java.security.MessageDigest; import org.mozilla.jss.crypto.X509Certificate; import org.mozilla.jss.*; import java.security.PublicKey; /* * The high-level interface takes care of all * the logic and cryptography. If you need to use the low-level interface, * please let us know what you are using it for. Perhaps it should be part * of the high-level interface. */ /** * A CMS SignerInfo. */ public class SignerInfo implements ASN1Value { //////////////////////////////////////////////// // PKCS #9 attributes //////////////////////////////////////////////// private static final OBJECT_IDENTIFIER CONTENT_TYPE = OBJECT_IDENTIFIER.PKCS.subBranch(9).subBranch(3); private static final OBJECT_IDENTIFIER MESSAGE_DIGEST = OBJECT_IDENTIFIER.PKCS.subBranch(9).subBranch(4); /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Members /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// private INTEGER version; private SignerIdentifier signerIdentifier; private AlgorithmIdentifier digestAlgorithm; private SET signedAttributes; // [0] OPTIONAL private AlgorithmIdentifier digestEncryptionAlgorithm; private OCTET_STRING encryptedDigest; private SET unsignedAttributes; // [1] OPTIONAL /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Accessor methods /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// /** * Retrieves the version number of this SignerInfo. */ public INTEGER getVersion() { return version; } /** * Retrieves the SignerIdentifier. */ public SignerIdentifier getSignerIdentifier() { return signerIdentifier; } /** * Retrieves the DigestAlgorithm used in this SignerInfo. * * @exception NoSuchAlgorithmException If the algorithm is not * recognized by JSS. */ public DigestAlgorithm getDigestAlgorithm() throws NoSuchAlgorithmException { return DigestAlgorithm.fromOID( digestAlgorithm.getOID() ); } /** * Retrieves the DigestAlgorithmIdentifier used in this SignerInfo. */ public AlgorithmIdentifier getDigestAlgorithmIdentifer() { return digestAlgorithm; } /** * Retrieves the signed attributes, if they exist. * */ public SET getSignedAttributes() { return signedAttributes; } /** * Returns true if the signedAttributes field is present. */ public boolean hasSignedAttributes() { return (signedAttributes != null); } /** * Returns the raw signature (digest encryption) algorithm used in this * SignerInfo. * * @exception NoSuchAlgorithmException If the algorithm is not recognized * by JSS. */ public SignatureAlgorithm getDigestEncryptionAlgorithm() throws NoSuchAlgorithmException { return SignatureAlgorithm.fromOID( digestEncryptionAlgorithm.getOID() ); } /** * Returns the DigestEncryptionAlgorithmIdentifier used in this SignerInfo. */ public AlgorithmIdentifier getDigestEncryptionAlgorithmIdentifier() { return digestEncryptionAlgorithm; } /** * Retrieves the encrypted digest. */ public byte[] getEncryptedDigest() { return encryptedDigest.toByteArray(); } /** * Retrieves the unsigned attributes, if they exist. * */ public SET getUnsignedAttributes() { return unsignedAttributes; } /** * Returns true if the unsignedAttributes field is present. */ public boolean hasUnsignedAttributes() { return (unsignedAttributes!=null); } /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// /** * A constructor for creating a new SignerInfo from scratch. * * @param signerIdentifier The signerIdentifier of the * certificate from which the public key was extracted to create * this SignerInfo. * @param signingAlg The algorithm to be used to sign the content. * This should be a composite algorithm, such as * RSASignatureWithMD5Digest, instead of a raw algorithm, such as * RSASignature. * Note that the digest portion of this algorithm must be the same * algorithm as was used to digest the message content. * @param signedAttributes An optional set of Attributes, which * will be signed along with the message content. This parameter may * be null, or the SET may be empty. DO NOT insert * the PKCS #9 content-type or message-digest attributes. They will * be added automatically if they are necessary. * @param unsignedAttributes An optional set of Attributes, which * will be included in the SignerInfo but not signed. This parameter * may be null, or the SET may be empty. * @param messageDigest The digest of the message contents. The digest * must have been created with the digest algorithm specified by * the signingAlg parameter. * @param contentType The type of the ContentInfo that is being signed. * If it is not data, then the PKCS #9 attributes * content-type and message-digest will be automatically computed and * added to the signed attributes. */ public SignerInfo( SignerIdentifier signerIdentifier, SET signedAttributes, SET unsignedAttributes, OBJECT_IDENTIFIER contentType, byte[] messageDigest, SignatureAlgorithm signingAlg, PrivateKey signingKey ) throws InvalidKeyException, NoSuchAlgorithmException, NotInitializedException, SignatureException, TokenException { if (signerIdentifier == null) { throw new IllegalArgumentException("SignerIdentifier may not be null"); } this.signerIdentifier = signerIdentifier; if (SignerIdentifier.ISSUER_AND_SERIALNUMBER.equals(this.signerIdentifier.getType())) { this.version = new INTEGER(1); } else if (SignerIdentifier.SUBJECT_KEY_IDENTIFIER.equals(this.signerIdentifier.getType())) { this.version = new INTEGER(3); } else { throw new IllegalArgumentException("Unexpected SignerIdentifier type"); } this.digestAlgorithm = new AlgorithmIdentifier(signingAlg.getDigestAlg().toOID(),null); // if content-type is not data, add message-digest and content-type // to signed attributes. if( ! contentType.equals(ContentInfo.DATA) ) { if( signedAttributes == null ) { signedAttributes = new SET(); } Attribute attrib = new Attribute(CONTENT_TYPE, contentType); signedAttributes.addElement(attrib); attrib = new Attribute(MESSAGE_DIGEST, new OCTET_STRING(messageDigest) ); signedAttributes.addElement(attrib); } digestEncryptionAlgorithm = new AlgorithmIdentifier( signingAlg.toOID(),null ); if( signedAttributes != null ) { assert( signedAttributes.size() >= 2 ); this.signedAttributes = signedAttributes; } ////////////////////////////////////////////////// // create encrypted digest (signature) ////////////////////////////////////////////////// // compute the digest CryptoToken token = signingKey.getOwningToken(); Signature sig; byte[] toBeSigned = null; if (signedAttributes == null) { // just use the message digest of the content if (signingAlg.getRawAlg() == SignatureAlgorithm.RSASignature) { SEQUENCE digestInfo = createDigestInfo(messageDigest, false); toBeSigned = ASN1Util.encode(digestInfo); } else { toBeSigned = messageDigest; } sig = token.getSignatureContext(signingAlg.getRawAlg()); //data is already digested } else { byte[] encoding = ASN1Util.encode(signedAttributes); if (signingAlg.getRawAlg() == SignatureAlgorithm.RSASignature) { // put the digest in a DigestInfo SEQUENCE digestInfo = createDigestInfo(encoding, true); toBeSigned = ASN1Util.encode(digestInfo); sig = token.getSignatureContext(SignatureAlgorithm.RSASignature); } else { toBeSigned = encoding; sig = token.getSignatureContext(signingAlg); } } // encrypt the DER-encoded DigestInfo with the private key sig.initSign(signingKey); sig.update(toBeSigned); encryptedDigest = new OCTET_STRING(sig.sign()); if( unsignedAttributes != null ) { this.unsignedAttributes = unsignedAttributes; } } /** * A constructor for creating a new SignerInfo from its decoding. */ SignerInfo( INTEGER version, SignerIdentifier signerIdentifier, AlgorithmIdentifier digestAlgorithm, SET signedAttributes, AlgorithmIdentifier digestEncryptionAlgorithm, byte[] encryptedDigest, SET unsignedAttributes) { this.version = version; this.signerIdentifier = signerIdentifier; this.digestAlgorithm = digestAlgorithm; this.signedAttributes = signedAttributes; this.digestEncryptionAlgorithm = digestEncryptionAlgorithm; this.encryptedDigest = new OCTET_STRING(encryptedDigest); this.unsignedAttributes = unsignedAttributes; } /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Verification /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// /** * Verifies that this SignerInfo contains a valid signature of the * given message digest. If any signed attributes are present, * they are also validated. The verification algorithm is as follows: * Note that this does not verify the validity of the * the certificate itself, only the signature.
    * *
  • If no signed attributes are present, the content type is * verified to be data. Then it is verified that the message * digest passed * in, when encrypted with the given public key, matches the encrypted * digest in the SignerInfo. * *
  • If signed attributes are present, * two particular attributes must be present:
      *
    • PKCS #9 Content-Type, the type of content that is being signed. * This must match the contentType parameter. *
    • PKCS #9 Message-Digest, the digest of the content that is being * signed. This must match the messageDigest parameter. *
    * After these two attributes are verified to be both present and correct, * the encryptedDigest field of the SignerInfo is verified to be the * signature of the contents octets of the DER encoding of the * signedAttributes field. * *
* * @param messageDigest The hash of the content that is signed by this * SignerInfo. * @param contentType The type of the content that is signed by this * SignerInfo. * @exception ObjectNotFoundException If no certificate * matching the issuer name and serial number can be found. */ public void verify(byte[] messageDigest, OBJECT_IDENTIFIER contentType) throws NotInitializedException, NoSuchAlgorithmException, InvalidKeyException, TokenException, SignatureException, ObjectNotFoundException { CryptoManager cm = CryptoManager.getInstance(); if (signerIdentifier.getType().equals(SignerIdentifier.ISSUER_AND_SERIALNUMBER)) { IssuerAndSerialNumber issuerAndSerialNumber = signerIdentifier.getIssuerAndSerialNumber(); X509Certificate cert = cm.findCertByIssuerAndSerialNumber( ASN1Util.encode(issuerAndSerialNumber.getIssuer()), issuerAndSerialNumber.getSerialNumber() ); verify(messageDigest, contentType, cert.getPublicKey()); } else { assert( signerIdentifier.getType().equals(SignerIdentifier.SUBJECT_KEY_IDENTIFIER) ); // XXX Do we have method to get key using keyIdentifier } } /** * Verifies that this SignerInfo contains a valid signature of the * given message digest. If any signed attributes are present, * they are also validated. The verification algorithm is as follows:
    * *
  • If no signed attributes are present, the content type is * verified to be data. Then it is verified that the message * digest passed * in, when encrypted with the given public key, matches the encrypted * digest in the SignerInfo. * *
  • If signed attributes are present, * two particular attributes must be present:
      *
    • PKCS #9 Content-Type, the type of content that is being signed. * This must match the contentType parameter. *
    • PKCS #9 Message-Digest, the digest of the content that is being * signed. This must match the messageDigest parameter. *
    * After these two attributes are verified to be both present and correct, * the encryptedDigest field of the SignerInfo is verified to be the * signature of the contents octets of the DER encoding of the * signedAttributes field. * *
* * @param messageDigest The hash of the content that is signed by this * SignerInfo. * @param contentType The type of the content that is signed by this * SignerInfo. * @param pubkey The public key to use to verify the signature. */ public void verify(byte[] messageDigest, OBJECT_IDENTIFIER contentType, PublicKey pubkey) throws NotInitializedException, NoSuchAlgorithmException, InvalidKeyException, TokenException, SignatureException { if( signedAttributes == null ) { verifyWithoutSignedAttributes(messageDigest, contentType, pubkey); } else { verifyWithSignedAttributes(messageDigest, contentType, pubkey); } } /** * Verifies that the message digest passed in, when encrypted with the * given public key, matches the encrypted digest in the SignerInfo. */ private void verifyWithoutSignedAttributes (byte[] messageDigest, OBJECT_IDENTIFIER contentType, PublicKey pubkey) throws NotInitializedException, NoSuchAlgorithmException, InvalidKeyException, TokenException, SignatureException { if( ! contentType.equals(ContentInfo.DATA) ) { // only data can be signed this way. Everything else has // to go into signedAttributes. throw new SignatureException( "Content-Type is not DATA, but there are"+ " no signed attributes"); } SignatureAlgorithm sigAlg = SignatureAlgorithm.fromOID( digestEncryptionAlgorithm.getOID() ); CryptoToken token = CryptoManager.getInstance() .getInternalCryptoToken(); Signature sig; byte[] toBeVerified; if (sigAlg.getRawAlg() == SignatureAlgorithm.RSASignature) { // create DigestInfo structure SEQUENCE digestInfo = createDigestInfo(messageDigest, false); toBeVerified = ASN1Util.encode(digestInfo); sig = token.getSignatureContext(sigAlg.getRawAlg()); } else { toBeVerified = messageDigest; sig = token.getSignatureContext(sigAlg); } sig.initVerify(pubkey); sig.update(toBeVerified); if( sig.verify(encryptedDigest.toByteArray()) ) { return; // success } else { throw new SignatureException( "Encrypted message digest parameter does not "+ "match encrypted digest in SignerInfo"); } } /** * Verifies a SignerInfo with signed attributes. If signed * attributes are present, then two particular attributes must * be present:
    *
  • PKCS #9 Content-Type, the type of content that is being signed. * This must match the contentType parameter. *
  • PKCS #9 Message-Digest, the digest of the content that is being * signed. This must match the messageDigest parameter. *
* After these two attributes are verified to be both present and correct, * the encryptedDigest field of the SignerInfo is verified to be the * signature of the contents octets of the DER encoding of the * signedAttributes field. */ private void verifyWithSignedAttributes (byte[] messageDigest, OBJECT_IDENTIFIER contentType, PublicKey pubkey) throws NotInitializedException, NoSuchAlgorithmException, InvalidKeyException, TokenException, SignatureException { int numAttrib = signedAttributes.size(); if(numAttrib < 2) { throw new SignatureException( "At least two signed attributes must be present:"+ " content-type and message-digest"); } // go through the signed attributes, verifying the // interesting ones boolean foundContentType = false; boolean foundMessageDigest = false; for( int i = 0; i < numAttrib; i++ ) { if( ! (signedAttributes.elementAt(i) instanceof Attribute)) { throw new SignatureException( "Element of signedAttributes is not an Attribute"); } Attribute attrib = (Attribute) signedAttributes.elementAt(i); if( attrib.getType().equals(CONTENT_TYPE) ) { // content-type. Compare with what was passed in. SET vals = attrib.getValues(); if( vals.size() != 1 ) { throw new SignatureException( "Content-Type attribute "+ " does not have exactly one value"); } ASN1Value val = vals.elementAt(0); OBJECT_IDENTIFIER ctype; try { if( val instanceof OBJECT_IDENTIFIER ) { ctype = (OBJECT_IDENTIFIER) val; } else if( val instanceof ANY ) { ctype = (OBJECT_IDENTIFIER) ((ANY)val).decodeWith( OBJECT_IDENTIFIER.getTemplate() ); } else { // what the heck is it? not what it's supposed to be throw new InvalidBERException( "Content-Type signed attribute has unexpected"+ " content type"); } } catch( InvalidBERException e ) { throw new SignatureException( "Content-Type signed attribute does not have "+ "OBJECT IDENTIFIER value"); } // compare the content type in the attribute to the // contentType parameter if( ! ctype.equals( contentType ) ) { throw new SignatureException( "Content-type in signed attributes does not "+ "match content-type being verified"); } // content type is A-OK foundContentType = true; } else if( attrib.getType().equals(MESSAGE_DIGEST) ) { SET vals = attrib.getValues(); if( vals.size() != 1 ) { throw new SignatureException( "Message-digest attribute does not have"+ " exactly one value"); } ASN1Value val = vals.elementAt(0); byte[] mdigest; try { if( val instanceof OCTET_STRING ) { mdigest = ((OCTET_STRING)val).toByteArray(); } else if( val instanceof ANY ) { OCTET_STRING os; os = (OCTET_STRING) ((ANY)val).decodeWith( OCTET_STRING.getTemplate() ); mdigest = os.toByteArray(); } else { // what the heck is it? not what it's supposed to be throw new InvalidBERException( "Content-Type signed attribute has unexpected"+ " content type"); } } catch( InvalidBERException e ) { throw new SignatureException( "Message-digest attribute does not"+ " have OCTET STRING value"); } // compare the message digest in the attribute to the // message digest being verified if( ! byteArraysAreSame(mdigest, messageDigest) ) { throw new SignatureException( "Message-digest attribute does not"+ " match message digest being verified"); } // message digest is A-OK foundMessageDigest = true; } // we don't care about other attributes } if( !foundContentType ) { throw new SignatureException( "Signed attributes does not contain"+ " PKCS #9 content-type attribute"); } if( !foundMessageDigest ) { throw new SignatureException( "Signed attributes does not contain"+ " PKCS #9 message-digest attribute"); } SignatureAlgorithm sigAlg = SignatureAlgorithm.fromOID( digestEncryptionAlgorithm.getOID() ); // All the signed attributes are present and correct. // Now verify the signature. CryptoToken token = CryptoManager.getInstance().getInternalCryptoToken(); Signature sig; // verify the contents octets of the DER encoded signed attribs byte[] encoding = ASN1Util.encode(signedAttributes); byte[] toBeVerified; if (sigAlg.getRawAlg() == SignatureAlgorithm.RSASignature) { // create DigestInfo structure SEQUENCE digestInfo = createDigestInfo(encoding, true); toBeVerified = ASN1Util.encode(digestInfo); sig = token.getSignatureContext(SignatureAlgorithm.RSASignature); } else { toBeVerified = encoding; sig = token.getSignatureContext(sigAlg); } sig.initVerify(pubkey); sig.update( toBeVerified ); if( ! sig.verify(encryptedDigest.toByteArray()) ) { // signature is invalid throw new SignatureException("encryptedDigest was not the correct"+ " signature of the contents octets of the DER-encoded"+ " signed attributes"); } // SUCCESSFULLY VERIFIED } private SEQUENCE createDigestInfo(byte[] data, boolean doDigest) throws NoSuchAlgorithmException { if(data == null || data.length == 0){ throw new IllegalArgumentException("Data to digest must be supplied"); } SEQUENCE digestInfo = new SEQUENCE(); digestInfo.addElement(this.digestAlgorithm); byte[] digest; if (doDigest) { MessageDigest md = MessageDigest.getInstance( DigestAlgorithm.fromOID(this.digestAlgorithm.getOID()).toString()); digest = md.digest(data); } else { digest = data; } digestInfo.addElement(new OCTET_STRING(digest)); return digestInfo; } /** * Compares two non-null byte arrays. Returns true if they are identical, * false otherwise. */ private static boolean byteArraysAreSame(byte[] left, byte[] right) { assert(left!=null && right!=null); if( left.length != right.length ) { return false; } for(int i = 0 ; i < left.length ; i++ ) { if( left[i] != right[i] ) { return false; } } return true; } /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // DER-encoding /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(getTag(),ostream); } @Override public void encode(Tag tag, OutputStream ostream) throws IOException { SEQUENCE sequence = new SEQUENCE(); sequence.addElement( version ); sequence.addElement( signerIdentifier ); sequence.addElement( digestAlgorithm ); if( signedAttributes != null ) { sequence.addElement( new Tag(0), signedAttributes ); } sequence.addElement( digestEncryptionAlgorithm ); sequence.addElement( encryptedDigest ); if( unsignedAttributes != null ) { sequence.addElement( new Tag(1), unsignedAttributes ); } sequence.encode(tag,ostream); } public static Template getTemplate() { return templateInstance; } private static Template templateInstance = new Template(); /** * A template for decoding a SignerInfo blob * */ public static class Template implements ASN1Template { SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); // serial number seqt.addElement(INTEGER.getTemplate()); // vn // issuerAndSerialNumber seqt.addElement(SignerIdentifier.getTemplate()); // signerId // digestAlgorithm seqt.addElement(AlgorithmIdentifier.getTemplate()); // digest alg // signedAttributes seqt.addOptionalElement( new Tag(0), new SET.OF_Template(Attribute.getTemplate())); // digestEncryptionAlgorithm seqt.addElement(AlgorithmIdentifier.getTemplate()); // dig encr alg // encryptedDigest seqt.addElement(OCTET_STRING.getTemplate()); // encr digest // unsigned attributes seqt.addOptionalElement( new Tag(1), new SET.OF_Template(Attribute.getTemplate())); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG,istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag,istream); assert(seq.size() == 7); return new SignerInfo( (INTEGER) seq.elementAt(0), (SignerIdentifier) seq.elementAt(1), (AlgorithmIdentifier) seq.elementAt(2), (SET) seq.elementAt(3), (AlgorithmIdentifier) seq.elementAt(4), ((OCTET_STRING) seq.elementAt(5)).toByteArray(), (SET) seq.elementAt(6) ); } } // end of template } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/cms/package.html000066400000000000000000000004261412550063600240260ustar00rootroot00000000000000 Creating and interpeting CMS blobs. jss-5.0.0/src/main/java/org/mozilla/jss/pkix/crmf/000077500000000000000000000000001412550063600217105ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/pkix/crmf/CertId.java000066400000000000000000000074521412550063600237350ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.crmf; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * CRMF CertId. *
 * CertId ::= SEQUENCE {
 *      issuer          GeneralName,
 *      serialNumber    INTEGER }
 * 
*/ public class CertId implements ASN1Value { /////////////////////////////////////////////////////////////////////// // Members and member access /////////////////////////////////////////////////////////////////////// private ANY issuer; private INTEGER serialNumber; private SEQUENCE sequence; /** * Returns the issuer field as an ANY. * The actual type of the field is GeneralName. */ public ANY getIssuer() { return issuer; } /** * Returns the serialNumber field. */ public INTEGER getSerialNumber() { return serialNumber; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * Constructs a new CertId from its components. Neither * component may be null. */ public CertId(ANY issuer, INTEGER serialNumber) { if( issuer == null || serialNumber == null ) { throw new IllegalArgumentException( "parameter to CertId constructor is null"); } sequence = new SEQUENCE(); this.issuer = issuer; sequence.addElement(issuer); this.serialNumber = serialNumber; sequence.addElement(serialNumber); } /////////////////////////////////////////////////////////////////////// // encoding/decoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template for decoding a CertId. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( ANY.getTemplate() ); seqt.addElement( INTEGER.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new CertId( (ANY) seq.elementAt(0), (INTEGER) seq.elementAt(1) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/crmf/CertReqMsg.java000066400000000000000000000260401412550063600245710ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.crmf; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigInteger; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.SignatureException; import java.text.DateFormat; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BIT_STRING; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.InvalidKeyFormatException; import org.mozilla.jss.crypto.Signature; import org.mozilla.jss.crypto.SignatureAlgorithm; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.pkix.primitive.AVA; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo; /** * This class models a CRMF CertReqMsg structure. */ public class CertReqMsg implements ASN1Value { public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } /** * Retrieves the CertRequest contained in this structure. */ public CertRequest getCertReq() { return certReq; } private CertRequest certReq; /** * Returns true if this CertReqMsg has a * regInfo field. */ public boolean hasRegInfo() { return regInfo != null; } /** * Returns the regInfo field. Should only be called if the * field is present. */ public SEQUENCE getRegInfo() { assert(regInfo != null); return regInfo; } private SEQUENCE regInfo; /** * Returns true if this CertReqMsg has a * pop field. */ public boolean hasPop() { return pop != null; } /** * Returns the pop field. Should only be called if the * field is present. */ public ProofOfPossession getPop() { assert(pop != null); return pop; } private ProofOfPossession pop = null; /** * Constructs a CertReqmsg from a CertRequest and, optionally, * a pop and a regInfo. * @param pop May be NULL. * @param regInfo May be NULL. */ public CertReqMsg( CertRequest certReq, ProofOfPossession pop, SEQUENCE regInfo ) { this.certReq = certReq; this.pop = pop; this.regInfo = regInfo; } /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // Verification /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// public void verify() throws SignatureException, InvalidKeyFormatException, NoSuchAlgorithmException, org.mozilla.jss.NotInitializedException, TokenException, java.security.InvalidKeyException, IOException{ CryptoToken token = CryptoManager.getInstance() .getInternalCryptoToken(); verify(token); } public void verify(CryptoToken token) throws SignatureException, InvalidKeyFormatException, NoSuchAlgorithmException, org.mozilla.jss.NotInitializedException, TokenException, java.security.InvalidKeyException, IOException{ ProofOfPossession.Type type = pop.getType(); if (type == ProofOfPossession.SIGNATURE) { POPOSigningKey sigkey = pop.getSignature(); AlgorithmIdentifier alg = sigkey.getAlgorithmIdentifier(); BIT_STRING sig_from = sigkey.getSignature(); ByteArrayOutputStream bo = new ByteArrayOutputStream(); certReq.encode(bo); byte[] toBeVerified = bo.toByteArray(); PublicKey pubkey = null; CertTemplate ct = certReq.getCertTemplate(); if (ct.hasPublicKey()) { SubjectPublicKeyInfo spi = ct.getPublicKey(); pubkey = spi.toPublicKey(); } SignatureAlgorithm sigAlg = SignatureAlgorithm.fromOID(alg.getOID()); Signature sig = token.getSignatureContext(sigAlg); sig.initVerify(pubkey); sig.update(toBeVerified); if( sig.verify(sig_from.getBits()) ) { //System.out.println("worked!!"); return; // success } else { throw new SignatureException( "Signed request information does not "+ "match signature in POP"); } } else if (type == ProofOfPossession.KEY_ENCIPHERMENT) { POPOPrivKey keyEnc = pop.getKeyEncipherment(); POPOPrivKey.Type ptype = keyEnc.getType(); if (ptype == POPOPrivKey.THIS_MESSAGE) { //BIT_STRING thisMessage = keyEnc.getThisMessage(); //This should be the same as from the archive control //It's verified by DRM. } else if (ptype == POPOPrivKey.SUBSEQUENT_MESSAGE) { new ChallengeResponseException("requested"); } } } /** * Encodes this CertReqMsg to the given OutputStream using * DER encoding. */ @Override public void encode(OutputStream ostream) throws IOException { //Assert.notYetImplemented("CertReqMsg encoding"); encode(getTag(),ostream); } /** * Encodes this CertReqMsg to the given OutputStream using * DER encoding, with the given implicit tag. */ @Override public void encode(Tag implicit, OutputStream ostream) throws IOException { //Assert.notYetImplemented("CertReqMsg encoding"); SEQUENCE sequence = new SEQUENCE(); sequence.addElement( certReq ); if (pop != null) sequence.addElement( pop ); if (regInfo != null) sequence.addElement( regInfo ); sequence.encode(implicit,ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A class for decoding CertReqMsg structures from a BER encoding. */ public static class Template implements ASN1Template { @Override public boolean tagMatch(Tag t) { return TAG.equals(t); } /** * Decodes a CertReqMsg from the given input stream. * * @return A new CertReqMsg. The return value may be cast * to a CertReqMsg. * @throws InvalidBERException If the data on the input stream is not * a valid BER encoding of a CertReqMsg. */ @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } /** * Decodes a CertReqMsg from the given input stream, using * the given implicit tag. * * @param implicit The implicit tag for this item. This must be * supplied if the CertReqMsg appears in a context * where it is implicitly tagged. * @return A new CertReqMsg. The return value may be cast * to a CertReqMsg. * @throws InvalidBERException If the data on the input stream is not * a valid BER encoding of a CertReqMsg. */ @Override public ASN1Value decode(Tag implicit, InputStream istream) throws IOException, InvalidBERException { SEQUENCE.Template seqt = new SEQUENCE.Template(); seqt.addElement( new CertRequest.Template() ); seqt.addOptionalElement( new ProofOfPossession.Template()); seqt.addOptionalElement( new SEQUENCE.OF_Template( new AVA.Template() ) ); SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); return new CertReqMsg( (CertRequest) seq.elementAt(0), (ProofOfPossession) seq.elementAt(1), (SEQUENCE) seq.elementAt(2) ); } } public static void main(String args[]) { try { if( args.length < 1 ) { System.err.println("Give an arg"); System.exit(0); } SEQUENCE.OF_Template seqt = new SEQUENCE.OF_Template( new CertReqMsg.Template() ); SEQUENCE seq=null; byte[] bytes; try (FileInputStream fis = new FileInputStream(args[0])) { bytes = new byte[fis.available()]; fis.read(bytes); } for(int i=0; i < 1; i++) { seq = (SEQUENCE) seqt.decode(new ByteArrayInputStream(bytes)); } System.out.println("Decoded "+seq.size()+" messages"); CertReqMsg reqmsg = (CertReqMsg) seq.elementAt(0); CertRequest certreq = reqmsg.getCertReq(); System.out.println("Request ID: "+certreq.getCertReqId() ); CertTemplate temp = certreq.getCertTemplate(); if( temp.hasVersion() ) { System.out.println("Version: "+temp.getVersion()); } else { System.out.println("No version"); } if( temp.hasSerialNumber() ) { System.out.println("Serial Number: "+temp.getSerialNumber()); } else { System.out.println("No serial number"); } if( temp.hasSigningAlg() ) { System.out.println("SigningAlg: "+temp.getSigningAlg().getOID()); } else { System.out.println("No signing alg"); } if( temp.hasIssuer() ) { System.out.println("Issuer: "+temp.getIssuer().getRFC1485()); } else { System.out.println("No issuer"); } if( temp.hasSubject() ) { System.out.println("Subject: "+temp.getSubject().getRFC1485()); } else { System.out.println("No subject: "); } if( temp.hasPublicKey() ) { System.out.println("Public Key: "+ temp.getPublicKey().getAlgorithmIdentifier().getOID() ); } else { System.out.println("No public key"); } if( temp.hasIssuerUID() ) { System.out.println("Issuer UID: "+new BigInteger(1, temp.getIssuerUID().getBits() ) ); } else { System.out.println("no issuer uid"); } if( temp.hasSubjectUID() ) { System.out.println("Subject UID: "+new BigInteger(1, temp.getIssuerUID().getBits() ) ); } else { System.out.println("no subject uid"); } if( temp.hasNotBefore() ) { System.out.println("Not Before: "+ DateFormat.getInstance().format( temp.getNotBefore() )); } if( temp.hasNotAfter() ) { System.out.println("Not After: "+ DateFormat.getInstance().format( temp.getNotAfter() )); } } catch( Exception e ) { e.printStackTrace(); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/crmf/CertRequest.java000066400000000000000000000114401412550063600250210ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.crmf; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.pkix.primitive.AVA; /** * A PKIX CertRequest. Currently can only be decoded from its BER * encoding. There are no methods for constructing one. */ public class CertRequest implements ASN1Value { private INTEGER certReqId; private CertTemplate certTemplate; private SEQUENCE controls; // may be null /** * @param certReqId May NOT be null. * @param certTemplate May NOT be null. * @param controls May be null. */ public CertRequest(INTEGER certReqId, CertTemplate certTemplate, SEQUENCE controls) { if( certReqId == null ) { throw new NullPointerException("certReqId is null"); } this.certReqId = certReqId; if( certTemplate == null ) { throw new NullPointerException("certTemplate is null"); } this.certTemplate = certTemplate; this.controls = controls; } /** * Returns the certReqId (certificate request ID) field. */ public INTEGER getCertReqId() { return certReqId; } /** * Returns the CertTemplate field. */ public CertTemplate getCertTemplate() { return certTemplate; } /** * Returns the controls field. */ public SEQUENCE getControls() { return controls; } /** * Returns the number of optional Controls in the cert request. * The number may be zero. */ public int numControls() { if(controls == null) { return 0; } else { return controls.size(); } } /** * Returns the ith Control. i must be in the * range [0..numControls-1]. */ public AVA controlAt(int i) { if( controls == null ) { throw new ArrayIndexOutOfBoundsException(); } return (AVA) controls.elementAt(i); } /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// // DER-encoding /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } /** * This method is not yet supported. */ @Override public void encode(OutputStream ostream) throws IOException { //Assert.notYetImplemented("CertRequest encoding"); encode(getTag(),ostream); } /** * This method is not yet supported. */ @Override public void encode(Tag implicit, OutputStream ostream) throws IOException { //Assert.notYetImplemented("CertRequest encoding"); SEQUENCE sequence = new SEQUENCE(); sequence.addElement( certReqId ); sequence.addElement( certTemplate ); if (controls != null) sequence.addElement( controls ); sequence.encode(implicit,ostream); } /** * A Template class for constructing CertRequests from their * BER encoding. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqTemplate; public Template() { seqTemplate = new SEQUENCE.Template(); seqTemplate.addElement( new INTEGER.Template() ); seqTemplate.addElement( new CertTemplate.Template() ); seqTemplate.addOptionalElement( new SEQUENCE.OF_Template( new AVA.Template() )); } @Override public boolean tagMatch( Tag tag ) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicit, InputStream istream) throws IOException, InvalidBERException { SEQUENCE seq = (SEQUENCE) seqTemplate.decode(implicit, istream); return new CertRequest( (INTEGER) seq.elementAt(0), (CertTemplate) seq.elementAt(1), (SEQUENCE) seq.elementAt(2) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/crmf/CertTemplate.java000066400000000000000000000374741412550063600251630ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.crmf; import org.mozilla.jss.asn1.*; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.io.IOException; import java.util.Date; import org.mozilla.jss.pkix.primitive.*; import org.mozilla.jss.pkix.cert.Extension; import java.util.Calendar; import java.util.TimeZone; /** * This class models a CRMF CertTemplate structure. */ public class CertTemplate implements ASN1Value { // All of these may be null private INTEGER version; private INTEGER serialNumber; private AlgorithmIdentifier signingAlg; private Name issuer; private Date notBefore; private Date notAfter; private Name subject; private SubjectPublicKeyInfo publicKey; private BIT_STRING issuerUID; private BIT_STRING subjectUID; private SEQUENCE extensions; /** * Creates an empty CertTemplate. Use the accessor methods to fill it * up with stuff. */ public CertTemplate() { } /** * Returns true if the version field is present. */ public boolean hasVersion() { return (version!=null); } /** * Returns the version field of this CertTemplate. */ public INTEGER getVersion() { return version; } /** * Sets the version field of this CertTemplate. */ public void setVersion(INTEGER version) { this.version = version; } /** * Returns true if the serialNumber field is present. */ public boolean hasSerialNumber() { return (serialNumber!=null); } /** * Returns the serialNumber field of this CertTemplate. */ public INTEGER getSerialNumber() { return serialNumber; } /** * Sets the serialNumber field of this CertTemplate. */ public void setSerialNumber(INTEGER serialNumber) { this.serialNumber = serialNumber; } /** * Returns true if the signingAlg field is present. */ public boolean hasSigningAlg() { return (signingAlg!=null); } /** * Returns the signingAlg field of this CertTemplate. */ public AlgorithmIdentifier getSigningAlg() { return signingAlg; } /** * Sets the signingAlg field of this CertTemplate. */ public void setSigningAlg(AlgorithmIdentifier signingAlg) { this.signingAlg = signingAlg; } /** * Returns true if the issuer field is present. */ public boolean hasIssuer() { return (issuer!=null); } /** * Returns the issuer field of this CertTemplate. */ public Name getIssuer() { return issuer; } /** * Sets the issuer field of this CertTemplate. */ public void setIssuer(Name issuer) { this.issuer = issuer; } /** * Returns true if the notBefore field is present. */ public boolean hasNotBefore() { return (notBefore!=null); } /** * Returns the notBefore field of this CertTemplate. */ public Date getNotBefore() { return notBefore; } /** * Sets the version field of this CertTemplate. */ public void setNotBefore(Date date) { this.notBefore = date; } /** * Returns true if the notAfter field is present. */ public boolean hasNotAfter() { return (notAfter!=null); } /** * Returns the notAfter field of this CertTemplate. */ public Date getNotAfter() { return notAfter; } /** * Sets the notAfter field of this CertTemplate. */ public void setNotAfter(Date date) { this.notAfter = date; } /** * Returns true if the subject field is present. */ public boolean hasSubject() { return (subject!=null); } /** * Sets the subject field of this CertTemplate. */ public Name getSubject() { return subject; } /** * Sets the subject field of this CertTemplate. */ public void setSubject(Name subject) { this.subject = subject; } /** * Returns true if the publicKey field is present. */ public boolean hasPublicKey() { return (publicKey!=null); } /** * Returns the publicKey field of this CertTemplate. */ public SubjectPublicKeyInfo getPublicKey() { return publicKey; } /** * Sets the publicKey field of this CertTemplate. */ public void setPublicKey(SubjectPublicKeyInfo publicKey) { this.publicKey = publicKey; } /** * Returns true if the issuerUID field is present. */ public boolean hasIssuerUID() { return (issuerUID!=null); } /** * Returns the issuerUID field of this CertTemplate. */ public BIT_STRING getIssuerUID() { return issuerUID; } /** * Sets the issuerUID field of this CertTemplate. */ public void setIssuerUID(BIT_STRING issuerUID) { this.issuerUID = issuerUID; } /** * Returns true if the subjectUID field is present. */ public boolean hasSubjectUID() { return (subjectUID!=null); } /** * Returns the subjectUID field of this CertTemplate. */ public BIT_STRING getSubjectUID() { return subjectUID; } /** * Sets the subjectUID field of this CertTemplate. */ public void setSubjectUID(BIT_STRING subjectUID) { this.subjectUID = subjectUID; } /** * Returns true if the extensions field is present. */ public boolean hasExtensions() { return (extensions!=null); } /** * Sets the extensions field of this CertTemplate. */ public void setExtensions(SEQUENCE extensions) { this.extensions = extensions; } /** * Returns the number of extensions present in the template. May be zero. */ public int numExtensions() { if(extensions == null) { return 0; } else { return extensions.size(); } } /** * Returns the ith extension. * @param idx The index of the extension to retrieve. Must be in the * range [ 0, numExtensions()-1 ]. */ public Extension extensionAt(int idx) { if(extensions == null) { throw new ArrayIndexOutOfBoundsException(); } return (Extension) extensions.elementAt(idx); } public void print(PrintStream ps, int indentSpaces) throws InvalidBERException, IOException { StringBuffer indentBuf = new StringBuffer(); for(int i=0; i < indentSpaces; i++) { indentBuf.append(" "); } String indent = indentBuf.toString(); if(version!=null) { ps.println("Version: "+version.toString()); } if(serialNumber!=null) { ps.println("Serial Number: "+serialNumber.toString()); } if(signingAlg!=null) { ps.println("Signing Algorithm: "+signingAlg.getOID().toString()); } if(issuer!=null) { ps.println("Issuer: "+issuer.getRFC1485()); } if(notBefore!=null) { ps.println("Not Before: " + notBefore); } if(notAfter!=null) { ps.println("Not After: " + notAfter); } if(subject!=null) { ps.println("Subject: " + subject.getRFC1485()); } if(publicKey!=null) { ps.println("publicKey is present"); } if(issuerUID != null ) { ps.println("issuerUID is present"); } if(subjectUID != null ) { ps.println("subjectUID is present"); } if(extensions != null ) { ps.println("Extensions is present, with "+extensions.size()+ " elements"); } } public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } // the last year for using UTCTime static final int UTCTIME_CUTOFF_YEAR = 2049; /** * Converts a Date into a UTCTime or GeneralizedTime, depending on * whether it falls before or after the cutoff date. */ private static TimeBase dateToASN1(Date d) { if(d==null) { return null; } Calendar cal = Calendar.getInstance( TimeZone.getTimeZone("GMT") ); cal.setTime(d); if( cal.get(Calendar.YEAR) <= UTCTIME_CUTOFF_YEAR) { return new UTCTime(d); } else { return new GeneralizedTime(d); } } @Override public void encode(Tag t, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); seq.addElement(Tag.get(0), version); seq.addElement(Tag.get(1), serialNumber); seq.addElement(Tag.get(2), signingAlg); if( issuer!=null ) { // issuer is a CHOICE, so it must be EXPLICITly tagged seq.addElement(new EXPLICIT(Tag.get(3), issuer )); } if( notBefore!=null || notAfter!=null ) { SEQUENCE optionalVal = new SEQUENCE(); // notBefore & notAfter are CHOICES, so must be EXPLICITly tagged if( notBefore!=null ) { optionalVal.addElement( new EXPLICIT( Tag.get(0), dateToASN1(notBefore) ) ); } if( notAfter!=null ) { optionalVal.addElement( new EXPLICIT( Tag.get(1), dateToASN1(notAfter) ) ); } seq.addElement(Tag.get(4), optionalVal); } if( subject!=null ) { // subject is a CHOICE, so it must be EXPLICITly tagged seq.addElement(new EXPLICIT(Tag.get(5), subject)); } seq.addElement(Tag.get(6), publicKey); seq.addElement(Tag.get(7), issuerUID); seq.addElement(Tag.get(8), subjectUID); seq.addElement(Tag.get(9), extensions); seq.encode(t, ostream); } private static Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A class for decoding CertTemplates. */ public static class Template implements ASN1Template { @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } /** * Decodes a CertTemplate from its BER encoding. The return * value of this method */ @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicit, InputStream istream) throws IOException, InvalidBERException { CHOICE.Template timeChoice = new CHOICE.Template(); timeChoice.addElement( new GeneralizedTime.Template() ); timeChoice.addElement( new UTCTime.Template() ); // optional validity. The times are CHOICEs, so they are // EXPLICITly tagged SEQUENCE.Template validity = new SEQUENCE.Template(); validity.addOptionalElement( new EXPLICIT.Template( Tag.get(0), timeChoice)); validity.addOptionalElement( new EXPLICIT.Template( Tag.get(1), timeChoice)); SEQUENCE.Template seqt = new SEQUENCE.Template(); seqt.addOptionalElement( Tag.get(0), new INTEGER.Template() ); seqt.addOptionalElement( Tag.get(1), new INTEGER.Template() ); seqt.addOptionalElement( Tag.get(2), new AlgorithmIdentifier.Template() ); seqt.addOptionalElement( new EXPLICIT.Template(Tag.get(3), new Name.Template() )); seqt.addOptionalElement( Tag.get(4), validity ); seqt.addOptionalElement( new EXPLICIT.Template(Tag.get(5), new Name.Template() )); seqt.addOptionalElement( Tag.get(6), new SubjectPublicKeyInfo.Template() ); seqt.addOptionalElement( Tag.get(7), new BIT_STRING.Template() ); seqt.addOptionalElement( Tag.get(8), new BIT_STRING.Template() ); seqt.addOptionalElement( Tag.get(9), new SEQUENCE.OF_Template( new Extension.Template() ) ); SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); CertTemplate ct = new CertTemplate(); ct.setVersion( (INTEGER) seq.elementAt(0) ); ct.setSerialNumber( (INTEGER) seq.elementAt(1) ); ct.setSigningAlg( (AlgorithmIdentifier) seq.elementAt(2) ); if( seq.elementAt(3) != null ) { ct.setIssuer((Name)((EXPLICIT)seq.elementAt(3)).getContent() ); } // validity EXPLICIT explicit; CHOICE choice; ASN1Value val; if( seq.elementAt(4) != null ) { explicit = (EXPLICIT) ((SEQUENCE)seq.elementAt(4)).elementAt(0); if( explicit != null ) { choice = (CHOICE) explicit.getContent(); val = choice.getValue(); if( val instanceof TimeBase ) { ct.setNotBefore( ((TimeBase)val).toDate() ); } } explicit = (EXPLICIT) ((SEQUENCE)seq.elementAt(4)).elementAt(1); if( explicit != null ) { choice = (CHOICE) explicit.getContent(); val = choice.getValue(); if( val instanceof TimeBase ) { ct.setNotAfter( ((TimeBase)val).toDate() ); } } } if( seq.elementAt(5) != null ) { ct.setSubject((Name)((EXPLICIT)seq.elementAt(5)).getContent() ); } ct.setPublicKey( (SubjectPublicKeyInfo) seq.elementAt(6) ); ct.setIssuerUID( (BIT_STRING) seq.elementAt(7) ); ct.setSubjectUID( (BIT_STRING) seq.elementAt(8) ); ct.setExtensions( (SEQUENCE) seq.elementAt(9) ); return ct; } } public static void main(String args[]) { try { CertTemplate ct = new CertTemplate(); Name name; ct.setVersion(new INTEGER(5)); ct.setSerialNumber(new INTEGER(13112)); name = new Name(); name.addCommonName("You"); name.addStateOrProvinceName("California"); ct.setIssuer(name); ct.setNotBefore(new Date()); name = new Name(); name.addCommonName("Me"); name.addCountryName("US"); ct.setSubject(name); ct.setIssuerUID( new BIT_STRING( new byte[] {0x00, 0x01}, 0 ) ); System.out.println("Constructed CertTemplate:"); byte[] encoded = ASN1Util.encode(ct); java.io.FileOutputStream fos = new java.io.FileOutputStream("certTemplate"); fos.write(encoded); fos.close(); ct.print(System.out, 0); CertTemplate newCt = (CertTemplate) ASN1Util.decode( CertTemplate.getTemplate(), encoded ); System.out.println("\nDecoded CertTemplate:"); newCt.print(System.out, 0); } catch( Exception e ) { e.printStackTrace(); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/crmf/ChallengeResponseException.java000066400000000000000000000025101412550063600300310ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.crmf; /** * An exception thrown when challenge response pop is requested. */ public class ChallengeResponseException extends java.lang.Exception { private static final long serialVersionUID = 1L; private ChallengeResponseException child=null; public ChallengeResponseException(String mesg) { super(mesg); } public ChallengeResponseException(ChallengeResponseException e, String mesg) { super(mesg); child = e; } /** * Prints out the exception class and error message, including * all the nested exceptions. */ @Override public String toString() { if(child != null) { return (super.toString()+ " >> " + child.toStringNested()); } else { return super.toString(); } } /** * Prints out the error message of this exception, including all the * nested exceptions. */ public String toStringNested() { if(child != null) { return ( getMessage() + " >> " + child.toStringNested()); } else { return getMessage(); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/crmf/Control.java000066400000000000000000000071641412550063600242030ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.crmf; import java.io.IOException; import java.io.InputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.asn1.UTF8String; import org.mozilla.jss.pkix.primitive.AVA; /** * A CRMF Control. */ public class Control extends AVA { // general CRMF OIDs public static final OBJECT_IDENTIFIER id_pkix = new OBJECT_IDENTIFIER( new long[] { 1, 3, 6, 1, 5, 5, 7 } ); public static final OBJECT_IDENTIFIER id_pkip = id_pkix.subBranch( 5 ); public static final OBJECT_IDENTIFIER id_regCtrl = id_pkip.subBranch( 1 ); // Control OIDs public static final OBJECT_IDENTIFIER id_regCtrl_regToken = id_regCtrl.subBranch(1); public static final OBJECT_IDENTIFIER id_regCtrl_authenticator = id_regCtrl.subBranch(2); public static final OBJECT_IDENTIFIER id_regCtrl_pkiPublicationInfo = id_regCtrl.subBranch(3); public static final OBJECT_IDENTIFIER id_regCtrl_pkiArchiveOptions = id_regCtrl.subBranch(4); public static final OBJECT_IDENTIFIER id_regCtrl_oldCertID = id_regCtrl.subBranch(5); public static final OBJECT_IDENTIFIER id_regCtrl_protocolEncrKey = id_regCtrl.subBranch(6); public Control(OBJECT_IDENTIFIER oid, ASN1Value value) { super(oid, value); } /** * Returns the value of this control as a UTF8String, if it actually * is a UTF8String. */ public UTF8String getUTF8String() throws InvalidBERException { return (UTF8String) getValue().decodeWith(UTF8String.getTemplate()); } /** * Returns the value of this control as a PKIArchiveOptions, if it * actually is a PKIArchiveOptions. */ public PKIArchiveOptions getPKIArchiveOptions() throws InvalidBERException { return (PKIArchiveOptions) getValue().decodeWith( PKIArchiveOptions.getTemplate() ); } /** * Returns the value of this control as a PKIPublicationInfo, if it * actually is a PKIPublicationInfo. */ public PKIPublicationInfo getPKIPublicationInfo() throws InvalidBERException { return (PKIPublicationInfo) getValue().decodeWith( PKIPublicationInfo.getTemplate() ); } /** * A template class for decoding a Control from a BER stream. */ public static class Template extends AVA.Template { private SEQUENCE.Template seqTemplate; public Template() { seqTemplate = new SEQUENCE.Template(); seqTemplate.addElement( new OBJECT_IDENTIFIER.Template() ); seqTemplate.addElement( new ANY.Template() ); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicit, InputStream istream) throws IOException, InvalidBERException { SEQUENCE seq = (SEQUENCE) seqTemplate.decode(implicit, istream); OBJECT_IDENTIFIER oid = (OBJECT_IDENTIFIER) seq.elementAt(0); ANY any = (ANY) seq.elementAt(1); return new Control( oid, any ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/crmf/EncryptedKey.java000066400000000000000000000117631412550063600251710ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.crmf; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.CHOICE; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; public class EncryptedKey implements ASN1Value { /** * The type of EncryptedKey. */ public static class Type { private Type() { } static final Type ENCRYPTED_VALUE = new Type(); static final Type ENVELOPED_DATA = new Type(); } public static final Type ENCRYPTED_VALUE = Type.ENCRYPTED_VALUE; public static final Type ENVELOPED_DATA = Type.ENVELOPED_DATA; /////////////////////////////////////////////////////////////////////// // member and member access /////////////////////////////////////////////////////////////////////// private Type type; private EncryptedValue encryptedValue; private ANY envelopedData; public Type getType() { return type; } /** * Should only be called if getType returns * ENCRYPTED_VALUE. */ public EncryptedValue getEncryptedValue() { return encryptedValue; } /** * Should only be called if getType returns * ENVELOPED_DATA. ANY is returned to prevent a circular * dependency between the org.mozilla.jss.pkcs7 package and the * org.mozilla.jss.pkix hierarchy. */ public ANY getEnvelopedData() { return envelopedData; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// public EncryptedKey(EncryptedValue encryptedValue) { this.type = ENCRYPTED_VALUE; this.encryptedValue = encryptedValue; this.tag = SEQUENCE.TAG; } public EncryptedKey(ANY envelopedData) { this.type = ENVELOPED_DATA; this.envelopedData = envelopedData; this.tag = new Tag(0); } /////////////////////////////////////////////////////////////////////// // encoding/decoding /////////////////////////////////////////////////////////////////////// private Tag tag; // set by constructor based on type @Override public Tag getTag() { return tag; } @Override public void encode(OutputStream ostream) throws IOException { encode(getTag(), ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { // no IMPLICIT tags allowed on ANY assert( getTag().equals(implicitTag)); if( type == ENCRYPTED_VALUE ) { assert( encryptedValue != null ); encryptedValue.encode(implicitTag, ostream); } else { assert(type == ENVELOPED_DATA); assert(envelopedData != null); envelopedData.encode(implicitTag, ostream); } } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template for decoding BER-encoded EncryptedKeys. */ public static class Template implements ASN1Template { private CHOICE.Template choicet; public Template() { choicet = new CHOICE.Template(); choicet.addElement( EncryptedValue.getTemplate() ); choicet.addElement( new Tag(0), ANY.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return choicet.tagMatch(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { try { CHOICE choice = (CHOICE) choicet.decode(istream); if( choice.getTag().equals(SEQUENCE.TAG) ) { return new EncryptedKey( (EncryptedValue) choice.getValue() ); } else { assert( choice.getTag().equals(new Tag(0)) ); return new EncryptedKey( (ANY) choice.getValue() ); } } catch(InvalidBERException e) { throw new InvalidBERException(e, "EncryptedKey"); } } /** * @param implicitTag This parameter is ignored, because a CHOICE * cannot have an implicitTag. */ @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { throw new RuntimeException("EncryptedKey, being a CHOICE, cannot be"+ " implicitly tagged"); // return decode(istream); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/crmf/EncryptedValue.java000066400000000000000000000144001412550063600255040ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.crmf; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BIT_STRING; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; /** * The CRMF structure EncryptedValue for storing the encrypted * key to be archived. */ public class EncryptedValue implements ASN1Value { /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private AlgorithmIdentifier intendedAlg; // may be null private AlgorithmIdentifier symmAlg; // may be null private BIT_STRING encSymmKey; // may be null private AlgorithmIdentifier keyAlg; // may be null private OCTET_STRING valueHint; // may be null private BIT_STRING encValue; // may be null private SEQUENCE sequence; /** * May return null. */ public AlgorithmIdentifier getIntendedAlg() { return intendedAlg; } /** * May return null. */ public AlgorithmIdentifier getSymmAlg() { return symmAlg; } /** * May return null. */ public BIT_STRING getEncSymmKey() { return encSymmKey; } /** * May return null. */ public AlgorithmIdentifier getKeyAlg() { return keyAlg; } /** * May return null. */ public OCTET_STRING getValueHint() { return valueHint; } public BIT_STRING getEncValue() { return encValue; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * @param intendedAlg May be null. * @param symmAlg May be null. * @param encSymmKey May be null. * @param keyAlg May be null. * @param valueHint May be null. * @param encValue May not be null. */ public EncryptedValue( AlgorithmIdentifier intendedAlg, AlgorithmIdentifier symmAlg, BIT_STRING encSymmKey, AlgorithmIdentifier keyAlg, OCTET_STRING valueHint, BIT_STRING encValue ) { if( encValue == null ) { throw new IllegalArgumentException("encValue is null"); } this.intendedAlg = intendedAlg; this.symmAlg = symmAlg; this.encSymmKey = encSymmKey; this.keyAlg = keyAlg; this.valueHint = valueHint; this.encValue = encValue; sequence = new SEQUENCE(); if(intendedAlg!=null) { sequence.addElement( new Tag(0), intendedAlg ); } if( symmAlg!=null ) { sequence.addElement( new Tag(1), symmAlg ); } if( encSymmKey!=null ) { sequence.addElement( new Tag(2), encSymmKey ); } if( keyAlg!=null ) { sequence.addElement( new Tag(3), keyAlg ); } if( valueHint!=null ) { sequence.addElement( new Tag(4), valueHint ); } sequence.addElement(encValue); } /////////////////////////////////////////////////////////////////////// // encoding/decoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template class for decoding BER-encoded EncryptedValues. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addOptionalElement( new Tag(0), AlgorithmIdentifier.getTemplate()); seqt.addOptionalElement( new Tag(1), AlgorithmIdentifier.getTemplate()); seqt.addOptionalElement( new Tag(2), BIT_STRING.getTemplate()); seqt.addOptionalElement( new Tag(3), AlgorithmIdentifier.getTemplate()); seqt.addOptionalElement( new Tag(4), OCTET_STRING.getTemplate()); seqt.addElement( BIT_STRING.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { try { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new EncryptedValue( (AlgorithmIdentifier) seq.elementAt(0), (AlgorithmIdentifier) seq.elementAt(1), (BIT_STRING) seq.elementAt(2), (AlgorithmIdentifier) seq.elementAt(3), (OCTET_STRING) seq.elementAt(4), (BIT_STRING) seq.elementAt(5) ); } catch(InvalidBERException e ) { throw new InvalidBERException(e, "EncryptedValue"); } } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/crmf/PKIArchiveOptions.java000066400000000000000000000157331412550063600260650ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.crmf; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BOOLEAN; import org.mozilla.jss.asn1.CHOICE; import org.mozilla.jss.asn1.EXPLICIT; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.Tag; public class PKIArchiveOptions implements ASN1Value { /** * A type of PKIArchiveOption. */ public static class Type { private Type() { } static final Type ENCRYPTED_PRIV_KEY = new Type(); static final Type KEY_GEN_PARAMETERS = new Type(); static final Type ARCHIVE_REM_GEN_PRIV_KEY = new Type(); } public static final Type ENCRYPTED_PRIV_KEY = Type.ENCRYPTED_PRIV_KEY; public static final Type KEY_GEN_PARAMETERS = Type.KEY_GEN_PARAMETERS; public static final Type ARCHIVE_REM_GEN_PRIV_KEY = Type.ARCHIVE_REM_GEN_PRIV_KEY; /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private EncryptedKey encryptedPrivKey; private OCTET_STRING keyGenParameters; private boolean archiveRemGenPrivKey; private Type type; /** * Returns the type of PKIArchiveOptions. */ public Type getType() { return type; } /** * Returns the encrypted key. Should only be called if the type * is ENCRYPTED_PRIV_KEY. */ public EncryptedKey getEncryptedKey( ) { assert(type == ENCRYPTED_PRIV_KEY); return encryptedPrivKey; } /** * Returns the key gen parameters. Should only be called if the type * is KEY_GEN_PARAMETERS. public byte[] getKeyGenParameters( ) { assert(type == KEY_GEN_PARAMETERS); return keyGenParameters; } /** * Returns the archiveRemGenPrivKey field, which indicates that * the sender wishes the receiver to generate and archive a key pair. * Should only be called if the type is * ARCHIVE_REM_GEN_PRIV_KEY. */ public boolean getArchiveRemGenPrivKey( ) { assert( type == ARCHIVE_REM_GEN_PRIV_KEY ); return archiveRemGenPrivKey; } /////////////////////////////////////////////////////////////////////// // constructors /////////////////////////////////////////////////////////////////////// public PKIArchiveOptions( EncryptedKey eKey ) { encryptedPrivKey = eKey; type = ENCRYPTED_PRIV_KEY; tag = new Tag(0); } public PKIArchiveOptions( byte[] keyGenParameters ) { this.keyGenParameters = new OCTET_STRING(keyGenParameters); type = KEY_GEN_PARAMETERS; tag = new Tag(1); } public PKIArchiveOptions( boolean archiveRemGenPrivKey ) { this.archiveRemGenPrivKey = archiveRemGenPrivKey; type = ARCHIVE_REM_GEN_PRIV_KEY; tag = new Tag(2); } /////////////////////////////////////////////////////////////////////// // encoding/decoding /////////////////////////////////////////////////////////////////////// private Tag tag; // set by the constructor depending on the type @Override public Tag getTag() { return tag; } /** * DER-encodes a PKIArchiveOptions. */ @Override public void encode(OutputStream ostream) throws IOException { encode( getTag(), ostream ); } /** * DER-encodes a PKIArchiveOptions. * @param implicitTag This parameter is ignored. A CHOICE cannot * have an implicit tag. */ @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { // no implicit tags on a CHOICE assert( implicitTag.equals(tag) ); if( type == ENCRYPTED_PRIV_KEY ) { // CHOICEs are always EXPLICITly tagged EXPLICIT explicit = new EXPLICIT( new Tag(0), encryptedPrivKey ); explicit.encode(tag, ostream); } else if( type == KEY_GEN_PARAMETERS ) { keyGenParameters.encode(tag, ostream); } else { assert( type == ARCHIVE_REM_GEN_PRIV_KEY ); (new BOOLEAN(archiveRemGenPrivKey)).encode(tag, ostream); } } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A template for decoding PKIArchiveOptions. */ public static class Template implements ASN1Template { CHOICE.Template template; public Template() { template = new CHOICE.Template(); // CHOICEs are always EXPLICIT template.addElement( new EXPLICIT.Template( new Tag(0), new EncryptedKey.Template() )); template.addElement( new Tag(1), new OCTET_STRING.Template() ); template.addElement( new Tag(2), new BOOLEAN.Template() ); } /** * Returns true if the given tag can satisfy this CHOICE. */ @Override public boolean tagMatch(Tag tag) { return template.tagMatch(tag); } /** * Decodes a PKIArchiveOptions. * @return A PKIArchiveOptions object. */ @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { CHOICE choice = (CHOICE) template.decode(istream); if( choice.getTag().getNum() == 0 ) { EncryptedKey ekey = (EncryptedKey) ((EXPLICIT)choice.getValue()).getContent(); return new PKIArchiveOptions(ekey); } else if( choice.getTag().getNum() == 1 ) { OCTET_STRING kgp = (OCTET_STRING) choice.getValue(); return new PKIArchiveOptions(kgp.toByteArray()); } else if( choice.getTag().getNum() == 2 ) { BOOLEAN arckey = (BOOLEAN) choice.getValue(); return new PKIArchiveOptions(arckey.toBoolean()); } else { String s = "Unrecognized tag in PKIArchiveOptions"; throw new InvalidBERException(s); } } /** * Decodes a PKIArchiveOptions. * @param implicitTag This parameter is ignored. Since * PKIArchiveOptions is a CHOICE, it cannot have an implicit tag. * @return A PKIArchiveOptions object. */ @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { return decode(istream); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/crmf/PKIPublicationInfo.java000066400000000000000000000126121412550063600262060ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.crmf; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * CRMF PKIPublicationInfo: *
 * PKIPublicationInfo ::= SEQUENCE {
 *      action          INTEGER {
 *          dontPublish     (0),
 *          pleasePublish   (1) },
 *      pubInfos SEQUENCE SIZE (1..MAX) OF SinglePubInfo OPTIONAL }
 *
 * SinglePubInfo ::= SEQUENCE {
 *      pubMethod       INTEGER {
 *          dontCare    (0),
 *          x500        (1),
 *          web         (2),
 *          ldap        (3) },
 *      pubLocation     GeneralName OPTIONAL }
 * 
*/ public class PKIPublicationInfo implements ASN1Value { /** * A PKIPublicationInfo action. */ public static final int DONT_PUBLISH = 0; /** * A PKIPublicationInfo action. */ public static final int PLEASE_PUBLISH = 1; /** * A SinglePubInfo publication method. */ public static final int DONT_CARE = 0; /** * A SinglePubInfo publication method. */ public static final int X500 = 1; /** * A SinglePubInfo publication method. */ public static final int WEB = 2; /** * A SinglePubInfo publication method. */ public static final int LDAP = 3; /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private int action; private SEQUENCE pubInfos; // may be null /** * Returns the action field. */ public int getAction() { return action; } /** * Returns the number of SinglePubInfos. May be zero. */ public int numPubInfos() { if( pubInfos == null ) { return 0; } else { return pubInfos.size(); } } /** * Returns the pubMethod in the SinglePubInfo at the given index. * Should return DONT_CARE, X500, WEB, or LDAP. */ public int getPubMethod(int index) { return ((INTEGER)((SEQUENCE)pubInfos.elementAt(index)). elementAt(0)).intValue(); } /** * Returns the pubLocation in the SinglePubInfo at the given index. * May return null, since pubLocation is an optional field. */ public ANY getPubLocation(int index) { return (ANY) ((SEQUENCE)pubInfos.elementAt(index)).elementAt(1); } /////////////////////////////////////////////////////////////////////// // constructors /////////////////////////////////////////////////////////////////////// /** * Creates a new PKIPublicationInfo. * @param action DONT_PUBLISH or PLEASE_PUBLISH. * @param pubInfos A SEQUENCE of SinglePubInfo, may be null. */ public PKIPublicationInfo(int action, SEQUENCE pubInfos) { this.action = action; this.pubInfos = pubInfos; } /////////////////////////////////////////////////////////////////////// // decoding/encoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); seq.addElement( new INTEGER(action) ); seq.addElement( pubInfos ); seq.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template for decoding a PKIPublicationInfo. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( INTEGER.getTemplate() ); SEQUENCE.Template pubInfot = new SEQUENCE.Template(); pubInfot.addElement(INTEGER.getTemplate()); pubInfot.addOptionalElement(ANY.getTemplate()); seqt.addOptionalElement( new SEQUENCE.OF_Template(pubInfot) ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new PKIPublicationInfo( ((INTEGER)seq.elementAt(0)).intValue(), (SEQUENCE) seq.elementAt(1) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/crmf/POPOPrivKey.java000066400000000000000000000167101412550063600246470ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.crmf; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BIT_STRING; import org.mozilla.jss.asn1.CHOICE; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.Tag; /** * CRMF POPOPrivKey: *
 * POPOPrivKey ::= CHOICE {
 *      thisMessage         [0] BIT STRING,
 *      subsequentMessage   [1] SubsequentMessage,
 *      dhMAC               [2] BIT STRING }
 *
 * SubsequentMessage ::= INTEGER {
 *      encrCert        (0),
 *      challengeResp   (1) }
 * 
*/ public class POPOPrivKey implements ASN1Value { /** * The type of POPOPrivKey. */ public static class Type { private Type() { } static final Type THIS_MESSAGE = new Type(); static final Type SUBSEQUENT_MESSAGE = new Type(); static final Type DHMAC = new Type(); } public static final Type THIS_MESSAGE = Type.THIS_MESSAGE; public static final Type SUBSEQUENT_MESSAGE = Type.SUBSEQUENT_MESSAGE; public static final Type DHMAC = Type.DHMAC; /** * The SubsequentMessage field is encrCert. */ public static final int ENCR_CERT = 0; /** * The SubsequentMessage field is challengeResp. */ public static final int CHALLENGE_RESP = 1; /////////////////////////////////////////////////////////////////////// // Members and member access /////////////////////////////////////////////////////////////////////// private Type type; private BIT_STRING thisMessage; // if type == THIS_MESSAGE private INTEGER subsequentMessage; // if type == SUBSEQUENT_MESSAGE private BIT_STRING dhMAC; // if type == DHMAC /** * Returns the type of POPOPrivKey: THIS_MESSAGE, SUBSEQUENT_MESSAGE, * or DHMAC. */ public Type getType() { return type; } /** * If type==THIS_MESSAGE, returns the thisMessage field. Otherwise, * returns null. */ public BIT_STRING getThisMessage() { return thisMessage; } /** * If type==SUBSEQUENT_MESSAGE, returns the subsequentMessage field. * Otherwise, returns null. The return value can be converted to an * integer and compared with ENCR_CERT and CHALLENGE_RESP. */ public INTEGER getSubsequentMessage() { return subsequentMessage; } /** * If type==DHMAC, returns the dhMAC field. Otherwise, returns null. */ public BIT_STRING getDhMAC() { return dhMAC; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// private POPOPrivKey() { } private POPOPrivKey(Type type, BIT_STRING thisMessage, INTEGER subsequentMessage, BIT_STRING dhMAC) { this.type = type; this.thisMessage = thisMessage; this.subsequentMessage = subsequentMessage; this.dhMAC = dhMAC; } /** * Creates a new POPOPrivKey with the given thisMessage field. */ public static POPOPrivKey createThisMessage(BIT_STRING thisMessage) { return new POPOPrivKey(THIS_MESSAGE, thisMessage, null, null); } /** * Creates a new POPOPrivKey with the given subsequentMessage field. */ public static POPOPrivKey createSubsequentMessage(int subsequentMessage) { if(subsequentMessage!=ENCR_CERT && subsequentMessage!=CHALLENGE_RESP) { throw new IllegalArgumentException( "Illegal subsequentMessage value: " + subsequentMessage ); } return new POPOPrivKey(SUBSEQUENT_MESSAGE, null, new INTEGER(subsequentMessage), null); } /** * Creates a new POPOPrivKey with the given dhMAC field. */ public static POPOPrivKey createDhMAC(BIT_STRING dhMAC) { return new POPOPrivKey(DHMAC, null, null, dhMAC); } /////////////////////////////////////////////////////////////////////// // encoding/decoding /////////////////////////////////////////////////////////////////////// @Override public Tag getTag() { if(type == THIS_MESSAGE) { return Tag.get(0); } else if(type == SUBSEQUENT_MESSAGE) { return Tag.get(1); } else { assert(type == DHMAC); return Tag.get(2); } } @Override public void encode(OutputStream ostream) throws IOException { if(type == THIS_MESSAGE) { thisMessage.encode(Tag.get(0), ostream); } else if(type == SUBSEQUENT_MESSAGE) { subsequentMessage.encode(Tag.get(1), ostream); } else { assert(type == DHMAC); dhMAC.encode(Tag.get(2), ostream); } } /** * Should not be called, because POPOPrivKey is a CHOICE and cannot have * an implicit tag. */ @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { throw new RuntimeException("POPOPrivKey is a CHOICE and cannot have an implicit tag"); // encode(ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template for decoding a POPOPrivKey. */ public static class Template implements ASN1Template { private CHOICE.Template choicet; public Template() { choicet = new CHOICE.Template(); choicet.addElement( Tag.get(0), BIT_STRING.getTemplate() ); choicet.addElement( Tag.get(1), INTEGER.getTemplate() ); choicet.addElement( Tag.get(2), BIT_STRING.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return choicet.tagMatch(tag); } /** * Should not be called, because POPOPrivKey is a CHOICE and cannot * have an implicit tag. */ @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { throw new RuntimeException("POPOPrivKey is a CHOICE and cannot have an implicitTag"); // return decode(istream); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { CHOICE choice = (CHOICE) choicet.decode(istream); Tag chosen = choice.getTag(); if( chosen.equals(Tag.get(0)) ) { return createThisMessage( (BIT_STRING) choice.getValue() ); } else if( chosen.equals(Tag.get(1)) ) { INTEGER I = (INTEGER) choice.getValue(); int i = I.intValue(); if( i != ENCR_CERT && i != CHALLENGE_RESP ) { throw new InvalidBERException( "SubsequentMessage has invalid value: "+i); } return createSubsequentMessage( i ); } else { assert( chosen.equals(Tag.get(2)) ); return createDhMAC( (BIT_STRING) choice.getValue() ); } } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/crmf/POPOSigningKey.java000066400000000000000000000112611412550063600253210ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.crmf; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BIT_STRING; import org.mozilla.jss.asn1.EXPLICIT; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; /** * CRMF POPOSigningKey: *
 * POPOSigningKey ::= SEQUENCE {
 *      poposkInput         [0] POPOSigningKeyInput OPTIONAL,
 *      algorithmIdentifier AlgorithmIdentifier,
 *      signature           BIT STRING }
 * 
*/ public class POPOSigningKey implements ASN1Value { /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private ANY poposkInput; // may be null private AlgorithmIdentifier algorithmIdentifier; private BIT_STRING signature; private SEQUENCE sequence; /** * Retrieves the input to the Proof-of-Possession of the signing key. * May return null, because this field is optional. Returns an ANY * because this type is not currently parsed. */ public ANY getPoposkInput() { return poposkInput; } /** * Retrieves the algorithm identifier for the signature. */ public AlgorithmIdentifier getAlgorithmIdentifier() { return algorithmIdentifier; } /** * Retrieves the signature. */ public BIT_STRING getSignature() { return signature; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * Creates a POPOSigningKey. * @param poposkInput May be null. */ public POPOSigningKey(ANY poposkInput, AlgorithmIdentifier algorithmIdentifier, BIT_STRING signature) { if(algorithmIdentifier==null || signature==null) { throw new IllegalArgumentException("parameter to POPOSigningKey"+ " constructor is null"); } this.poposkInput = poposkInput; this.algorithmIdentifier = algorithmIdentifier; this.signature = signature; sequence = new SEQUENCE(); sequence.addElement( Tag.get(0), poposkInput ); sequence.addElement( algorithmIdentifier ); sequence.addElement( signature ); } /////////////////////////////////////////////////////////////////////// // encoding/decoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(TAG, ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A Template for decoding POPOSigningKey. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addOptionalElement( new EXPLICIT.Template( Tag.get(0), ANY.getTemplate()) ); seqt.addElement( AlgorithmIdentifier.getTemplate()); seqt.addElement( BIT_STRING.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new POPOSigningKey( (ANY) seq.elementAt(0), (AlgorithmIdentifier) seq.elementAt(1), (BIT_STRING) seq.elementAt(2) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/crmf/ProofOfPossession.java000066400000000000000000000167031412550063600262220ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.crmf; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.CHOICE; import org.mozilla.jss.asn1.EXPLICIT; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.NULL; import org.mozilla.jss.asn1.Tag; /** * CRMF ProofOfPossession: *
 * ProofOfPossession ::= CHOICE {
 *      raVerified          [0] NULL,
 *      signature           [1] POPOSigningKey,
 *      keyEncipherment     [2] POPOPrivKey,
 *      keyAgreement        [3] POPOPrivKey }
 * 
*/ public class ProofOfPossession implements ASN1Value { /** * The type of ProofOfPossesion. */ public static class Type { private Type() { } static Type RA_VERIFIED = new Type(); static Type SIGNATURE = new Type(); static Type KEY_ENCIPHERMENT = new Type(); static Type KEY_AGREEMENT = new Type(); } public static Type RA_VERIFIED = Type.RA_VERIFIED; public static Type SIGNATURE = Type.SIGNATURE; public static Type KEY_ENCIPHERMENT = Type.KEY_ENCIPHERMENT; public static Type KEY_AGREEMENT = Type.KEY_AGREEMENT; /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private Type type; private POPOSigningKey signature; // if type == SIGNATURE private POPOPrivKey keyEncipherment; // if type == KEY_ENCIPHERMENT private POPOPrivKey keyAgreement; // if type == KEY_AGREEMENT /** * Returns the type of ProofOfPossesion:
    *
  • RA_VERIFIED *
  • SIGNATURE *
  • KEY_ENCIPHERMENT *
  • KEY_AGREEMENT *
*/ public Type getType() { return type; } /** * If type == SIGNATURE, returns the signature field. Otherwise, * returns null. */ public POPOSigningKey getSignature() { return signature; } /** * If type == KEY_ENCIPHERMENT, returns the keyEncipherment field. * Otherwise, returns null. */ public POPOPrivKey getKeyEncipherment() { return keyEncipherment; } /** * If type == KEY_AGREEMENT, returns the keyAgreement field. Otherwise, * returns null. */ public POPOPrivKey getKeyAgreement() { return keyAgreement; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// private ProofOfPossession() { } private ProofOfPossession(Type type, POPOSigningKey signature, POPOPrivKey keyEncipherment, POPOPrivKey keyAgreement) { this.type = type; this.signature = signature; this.keyEncipherment = keyEncipherment; this.keyAgreement = keyAgreement; } /** * Creates a new ProofOfPossesion with an raVerified field. */ public static ProofOfPossession createRaVerified() { return new ProofOfPossession( RA_VERIFIED, null, null, null ); } /** * Creates a new ProofOfPossesion with the given signature field. */ public static ProofOfPossession createSignature(POPOSigningKey signature) { return new ProofOfPossession( SIGNATURE, signature, null, null ); } /** * Creates a new ProofOfPossesion with the given keyEncipherment field. */ public static ProofOfPossession createKeyEncipherment(POPOPrivKey keyEncipherment) { return new ProofOfPossession( KEY_ENCIPHERMENT, null, keyEncipherment, null ); } /** * Creates a new ProofOfPossesion with the given keyAgreement field. */ public static ProofOfPossession createKeyAgreement(POPOPrivKey keyAgreement) { return new ProofOfPossession( KEY_AGREEMENT, null, null, keyAgreement ); } /////////////////////////////////////////////////////////////////////// // decoding/encoding /////////////////////////////////////////////////////////////////////// @Override public Tag getTag() { if( type == RA_VERIFIED ) { return Tag.get(0); } else if( type == SIGNATURE ) { return Tag.get(1); } else if( type == KEY_ENCIPHERMENT ) { return Tag.get(2); } else { assert( type == KEY_AGREEMENT ); return Tag.get(3); } } @Override public void encode(OutputStream ostream) throws IOException { if( type == RA_VERIFIED ) { (new NULL()).encode(Tag.get(0), ostream); } else if( type == SIGNATURE ) { signature.encode(Tag.get(1), ostream); } else if( type == KEY_ENCIPHERMENT ) { // a CHOICE must be explicitly tagged EXPLICIT e = new EXPLICIT( Tag.get(2), keyEncipherment ); e.encode(ostream); } else { assert( type == KEY_AGREEMENT ); // a CHOICE must be explicitly tagged EXPLICIT e = new EXPLICIT( Tag.get(3), keyAgreement ); e.encode(ostream); } } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { assert(implicitTag.equals(getTag())); encode(ostream); } /** * A Template for decoding a ProofOfPossession. */ public static class Template implements ASN1Template { private CHOICE.Template choicet; public Template() { choicet = new CHOICE.Template(); choicet.addElement( Tag.get(0), NULL.getTemplate() ); choicet.addElement( Tag.get(1), POPOSigningKey.getTemplate() ); EXPLICIT.Template et = new EXPLICIT.Template( Tag.get(2), POPOPrivKey.getTemplate() ); choicet.addElement( et ); et = new EXPLICIT.Template( Tag.get(3), POPOPrivKey.getTemplate() ); choicet.addElement( et ); } @Override public boolean tagMatch(Tag tag) { return choicet.tagMatch(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { CHOICE c = (CHOICE) choicet.decode(istream); if( c.getTag().equals(Tag.get(0)) ) { return createRaVerified(); } else if( c.getTag().equals(Tag.get(1)) ) { return createSignature( (POPOSigningKey) c.getValue() ); } else if( c.getTag().equals(Tag.get(2)) ) { EXPLICIT e = (EXPLICIT) c.getValue(); return createKeyEncipherment( (POPOPrivKey) e.getContent() ); } else { assert( c.getTag().equals(Tag.get(3)) ); EXPLICIT e = (EXPLICIT) c.getValue(); return createKeyAgreement( (POPOPrivKey) e.getContent() ); } } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { throw new RuntimeException("A CHOICE cannot be implicitly tagged"); // return decode(istream); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/crmf/package.html000066400000000000000000000004121412550063600241660ustar00rootroot00000000000000 The PKIX CRMF protocol. jss-5.0.0/src/main/java/org/mozilla/jss/pkix/primitive/000077500000000000000000000000001412550063600227715ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/pkix/primitive/AVA.java000066400000000000000000000061111412550063600242420ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.primitive; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * An AttributeValueAssertion, which has the following ASN.1 * definition (roughly): *
 *      AttributeValueAssertion ::= SEQUENCE {
 *          type        OBJECT IDENTIFIER,
 *          value       ANY DEFINED BY type }
 * 
*/ public class AVA implements ASN1Value { private OBJECT_IDENTIFIER oid; private ANY value; public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } public AVA(OBJECT_IDENTIFIER oid, ASN1Value value) { this.oid = oid; if( value instanceof ANY ) { this.value = (ANY) value; } else { byte[] encoded = ASN1Util.encode(value); try { this.value = (ANY) ASN1Util.decode(ANY.getTemplate(), encoded); } catch( InvalidBERException e ) { throw new RuntimeException("InvalidBERException while decoding as ANY: " + e.getMessage(), e); } } } public OBJECT_IDENTIFIER getOID() { return oid; } /** * Returns the value of this AVA, encoded as an ANY. */ public ANY getValue() { return value; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicit, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); seq.addElement(oid); seq.addElement(value); seq.encode(implicit, ostream); } /** * A Template for decoding an AVA. */ public static class Template implements ASN1Template { @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicit, InputStream istream) throws IOException, InvalidBERException { SEQUENCE.Template seqt = new SEQUENCE.Template(); seqt.addElement( new OBJECT_IDENTIFIER.Template() ); seqt.addElement( new ANY.Template() ); SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); // The template should have enforced this assert(seq.size() == 2); return new AVA( (OBJECT_IDENTIFIER) seq.elementAt(0), seq.elementAt(1) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/primitive/AlgorithmIdentifier.java000066400000000000000000000067771412550063600276060ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.primitive; import org.mozilla.jss.asn1.*; import java.io.InputStream; import java.io.OutputStream; import java.io.IOException; public class AlgorithmIdentifier implements ASN1Value { private OBJECT_IDENTIFIER oid; private ASN1Value parameters=null; private SEQUENCE sequence = new SEQUENCE(); public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } /** * Creates an AlgorithmIdentifier with no parameter. */ public AlgorithmIdentifier(OBJECT_IDENTIFIER oid) { this.oid = oid; sequence.addElement( oid ); } /** * Creates an AlgorithmIdentifier. * * @param parameters The algorithm parameters. A value of null * will be encoded with an ASN.1 NULL. */ public AlgorithmIdentifier(OBJECT_IDENTIFIER oid, ASN1Value parameters) { this.oid = oid; sequence.addElement( oid ); this.parameters = parameters; if( parameters != null ) { sequence.addElement(parameters); } else { sequence.addElement(new NULL()); } } public OBJECT_IDENTIFIER getOID() { return oid; } /** * If this instance was constructed, returns the * parameter passed in to the constructor. If this instance was * decoded from a template, returns an ANY that was read from the * BER stream. In either case, it will return null if no parameters * were supplied. */ public ASN1Value getParameters() { return parameters; } private static final AlgorithmIdentifier.Template templateInstance = new AlgorithmIdentifier.Template(); public static AlgorithmIdentifier.Template getTemplate() { return templateInstance; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicit, OutputStream ostream) throws IOException { sequence.encode(implicit, ostream); } public static class Template implements ASN1Template { @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicit, InputStream istream) throws IOException, InvalidBERException { SEQUENCE.Template seqt = new SEQUENCE.Template(); seqt.addElement( new OBJECT_IDENTIFIER.Template() ); seqt.addOptionalElement( new ANY.Template() ); SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); // the template should have enforced this assert( seq.size() == 2 ); OBJECT_IDENTIFIER algOID = (OBJECT_IDENTIFIER)seq.elementAt(0); if (seq.elementAt(1) == null) { return new AlgorithmIdentifier( algOID // OID ); } else { return new AlgorithmIdentifier( (OBJECT_IDENTIFIER)seq.elementAt(0), // OID seq.elementAt(1) // parameters ); } } } // end of Template } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/primitive/Attribute.java000066400000000000000000000061721412550063600256050ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.primitive; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ANY; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.SET; import org.mozilla.jss.asn1.Tag; /** * An Attribute, which has the following ASN.1 * definition (roughly): *
 *      Attribute ::= SEQUENCE {
 *          type        OBJECT IDENTIFIER,
 *          value       SET }
 * 
*/ public class Attribute implements ASN1Value { private OBJECT_IDENTIFIER type; private SET values; public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } public Attribute(OBJECT_IDENTIFIER type, SET values) { this.type = type; this.values = values; } public Attribute(OBJECT_IDENTIFIER type, ASN1Value value) { this.type = type; this.values = new SET(); values.addElement(value); } public OBJECT_IDENTIFIER getType() { return type; } /** * If this AVA was constructed, returns the SET of ASN1Values passed to the * constructor. If this Attribute was decoded with an Attribute.Template, * returns a SET of ANYs. */ public SET getValues() { return values; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicit, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); seq.addElement(type); seq.addElement(values); seq.encode(implicit, ostream); } public static Template getTemplate() { return templateInstance; } private static Template templateInstance = new Template(); /** * A Template for decoding an Attribute. */ public static class Template implements ASN1Template { @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicit, InputStream istream) throws IOException, InvalidBERException { SEQUENCE.Template seqt = new SEQUENCE.Template(); seqt.addElement( new OBJECT_IDENTIFIER.Template() ); seqt.addElement( new SET.OF_Template(new ANY.Template())); SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); // The template should have enforced this assert(seq.size() == 2); return new Attribute( (OBJECT_IDENTIFIER) seq.elementAt(0), (SET) seq.elementAt(1)); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/primitive/DirectoryString.java000066400000000000000000000133161412550063600267730ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.primitive; import java.io.CharConversionException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BMPString; import org.mozilla.jss.asn1.CHOICE; import org.mozilla.jss.asn1.CharacterString; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.PrintableString; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.asn1.TeletexString; import org.mozilla.jss.asn1.UTF8String; import org.mozilla.jss.asn1.UniversalString; /** * An X.500 DirectoryString. * DirectoryString is defined as follows: *
 * DirectoryString ::= CHOICE {
 *      teletexString               TeletexString (SIZE (1..MAX)),
 *      printableString             PrintableString (SIZE (1..MAX)),
 *      universalString             UniversalString (SIZE (1..MAX)),
 *      utf8String                  UTF8String (SIZE (1..MAX)),
 *      bmpString                   BMPString (SIZE (1..MAX))  }
 * 
*/ public class DirectoryString implements ASN1Value { private CharacterString asn1String; /** * Encodes a Java String into a Directory String. * The following rules for choosing an encoding are from the * IETF * PKIX document Internet X.509 Public Key Infrastructure: * Certificate and CRL Profile:
    *
  • The preferred encoding is UTF8String, and all certificates * issued after December 31, 2003, MUST use UTF8String encoding, * with a few exceptions. *
  • Until December 31, 2003, strings that fit in the PrintableString * character set MAY use PrintableString. *
  • Until December 31, 2003, string that fit in the BMPString character * set MAY use BMPString. *
  • Strings that fit in neither the PrintableString nor the BMPString * character set MUST use UTF8String. *
* This is all very nice, but for backwards compatibility, what we really * do is:
    *
  • Try PrintableString *
  • Try TeletexString *
  • Try UniversalString *
*/ public DirectoryString(String s) throws CharConversionException { try { try { asn1String = new PrintableString(s); } catch( CharConversionException e ) { asn1String = new TeletexString(s); } } catch( CharConversionException e ) { asn1String = new UniversalString(s); } } /** * Creates a DirectoryString from an ASN.1 string. * @param s Must be a TeletexString, PrintableString, UniversalString, * UTF8String, or BMPString. */ public DirectoryString(CharacterString s) { if( !(s instanceof PrintableString ) && !(s instanceof BMPString) && !(s instanceof UTF8String) && !(s instanceof TeletexString) && !(s instanceof UniversalString) ) { throw new IllegalArgumentException("DirectoryString must be "+ "TeletexString, PrintableString, UniversalString, UTF8STring,"+ " or BMPString"); } asn1String = s; } /** * Converts an ASN.1 DirectoryString to a Java string. */ @Override public String toString() { return asn1String.toString(); } @Override public Tag getTag() { return asn1String.getTag(); } @Override public void encode(OutputStream ostream) throws IOException { asn1String.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { asn1String.encode(implicitTag, ostream); } /** * Returns a singleton instance of the decoding template for this class. */ public static Template getTemplate() { return templateInstance; } private static final Template templateInstance = new Template(); /** * A Template for decoding DirectoryStrings from their BER encoding. */ public static class Template implements ASN1Template { private CHOICE.Template choicet; public Template() { choicet = new CHOICE.Template(); choicet.addElement( PrintableString.getTemplate() ); choicet.addElement( BMPString.getTemplate() ); choicet.addElement( UTF8String.getTemplate() ); choicet.addElement( TeletexString.getTemplate() ); choicet.addElement( UniversalString.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return choicet.tagMatch(tag); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { CHOICE choice = (CHOICE) choicet.decode(istream); return new DirectoryString( (CharacterString) choice.getValue()); } /** * @param implicitTag This parameter is ignored, because * DirectoryStrings (being CHOICEs) cannot have implicit tags. * @exception InvalidBERException If the encoding does not contain a * valid DirectoryString. */ @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws IOException, InvalidBERException { assert( tagMatch(implicitTag) ); return decode(istream); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/primitive/EncryptedPrivateKeyInfo.java000066400000000000000000000461111412550063600304140ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.primitive; import java.io.CharConversionException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.BadPaddingException; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.crypto.Cipher; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.EncryptionAlgorithm; import org.mozilla.jss.crypto.IVParameterSpec; import org.mozilla.jss.crypto.IllegalBlockSizeException; import org.mozilla.jss.crypto.KeyGenAlgorithm; import org.mozilla.jss.crypto.KeyGenerator; import org.mozilla.jss.crypto.KeyWrapAlgorithm; import org.mozilla.jss.crypto.KeyWrapper; import org.mozilla.jss.crypto.PBEAlgorithm; import org.mozilla.jss.crypto.PBEKeyGenParams; import org.mozilla.jss.crypto.PrivateKey; import org.mozilla.jss.crypto.SymmetricKey; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.util.Password; /** * PKCS #8 EncryptedPrivateKeyInfo. *
 * EncryptedPrivateKeyInfo ::= SEQUENCE {
 *      encryptionAlgorithm     AlgorithmIdentifier,
 *      encryptedData           OCTET STRING }
 * 
*/ public class EncryptedPrivateKeyInfo implements ASN1Value { /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private AlgorithmIdentifier encryptionAlgorithm; private OCTET_STRING encryptedData; private SEQUENCE sequence; public AlgorithmIdentifier getEncryptionAlgorithm() { return encryptionAlgorithm; } public OCTET_STRING getEncryptedData() { return encryptedData; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * Creates an EncryptedPrivateKeyInfo from its components. * */ public EncryptedPrivateKeyInfo( AlgorithmIdentifier encryptionAlgorithm, OCTET_STRING encryptedData) { if( encryptionAlgorithm==null || encryptedData==null ) { throw new IllegalArgumentException( "EncryptedPrivateKeyInfo parameter is null"); } this.encryptionAlgorithm = encryptionAlgorithm; this.encryptedData = encryptedData; sequence = new SEQUENCE(); sequence.addElement(encryptionAlgorithm); sequence.addElement(encryptedData); } /////////////////////////////////////////////////////////////////////// // crypto shortcuts /////////////////////////////////////////////////////////////////////// /** * Creates a new EncryptedPrivateKeyInfo, where the data is encrypted * with a password-based key. * * @param keyGenAlg The algorithm for generating a symmetric key from * a password, salt, and iteration count. * @param password The password to use in generating the key. * @param salt The salt to use in generating the key. * @param iterationCount The number of hashing iterations to perform * while generating the key. * @param charToByteConverter The mechanism for converting the characters * in the password into bytes. If null, the default mechanism * will be used, which is UTF8. * @param pki The PrivateKeyInfo to be encrypted and stored in the * EncryptedContentInfo. Before they are encrypted, they will be * padded using PKCS padding. */ public static EncryptedPrivateKeyInfo createPBE(PBEAlgorithm keyGenAlg, Password password, byte[] salt, int iterationCount, KeyGenerator.CharToByteConverter charToByteConverter, PrivateKeyInfo pki) throws NotInitializedException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException, TokenException, CharConversionException { try { // check key gen algorithm if( ! (keyGenAlg instanceof PBEAlgorithm) ) { throw new NoSuchAlgorithmException("Key generation algorithm"+ " is not a PBE algorithm"); } PBEAlgorithm pbeAlg = keyGenAlg; CryptoManager cman = CryptoManager.getInstance(); // generate key CryptoToken token = cman.getInternalCryptoToken(); KeyGenerator kg = token.getKeyGenerator( keyGenAlg ); PBEKeyGenParams pbekgParams = new PBEKeyGenParams( password, salt, iterationCount); if( charToByteConverter != null ) { kg.setCharToByteConverter( charToByteConverter ); } kg.initialize(pbekgParams); SymmetricKey key = kg.generate(); // generate IV EncryptionAlgorithm encAlg = pbeAlg.getEncryptionAlg(); AlgorithmParameterSpec params=null; Class [] paramClasses = encAlg.getParameterClasses(); for (int i = 0; i < paramClasses.length; i ++) { if ( paramClasses[i].equals( javax.crypto.spec.IvParameterSpec.class ) ) { params = new IVParameterSpec( kg.generatePBE_IV() ); break; } } // perform encryption Cipher cipher = token.getCipherContext( encAlg ); cipher.initEncrypt( key, params ); byte[] encrypted = cipher.doFinal( Cipher.pad( ASN1Util.encode(pki), encAlg.getBlockSize()) ); // make encryption algorithm identifier PBEParameter pbeParam = new PBEParameter( salt, iterationCount ); AlgorithmIdentifier encAlgID = new AlgorithmIdentifier( keyGenAlg.toOID(), pbeParam); // create EncryptedPrivateKeyInfo EncryptedPrivateKeyInfo epki = new EncryptedPrivateKeyInfo ( encAlgID, new OCTET_STRING(encrypted) ); return epki; } catch( IllegalBlockSizeException e ) { throw new RuntimeException("IllegalBlockSizeException in EncryptedContentInfo" +".createPBE: " + e.getMessage(), e); } catch( BadPaddingException e ) { throw new RuntimeException("BadPaddingException in EncryptedContentInfo" +".createPBE: " + e.getMessage(), e); } } /** * Export a private key in PBES2 format, using a random PBKDF2 salt. * * Token must support the CKM_PKCS5_PBKD2 mechanism. * * @param saltLen Length of salt in bytes (default: 16) * @param kdfIterations PBKDF2 iterations (default: 2000) * @param encAlg The symmetric encryption algorithm for enciphering the * private key. Determines the size of derived key. * @param pwd Password * @param charToByteConverter The mechanism for converting the characters * in the password into bytes. If null, the default mechanism * will be used, which is UTF8. * @param privateKeyInfo The encoded PrivateKeyInfo to be encrypted and * stored in the EncryptedContentInfo. */ public static EncryptedPrivateKeyInfo createPBES2( int saltLen, int kdfIterations, EncryptionAlgorithm encAlg, Password pwd, KeyGenerator.CharToByteConverter charToByteConverter, PrivateKeyInfo privateKeyInfo) throws NotInitializedException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException, TokenException, CharConversionException { if (encAlg == null) throw new IllegalArgumentException("encAlg cannot be null"); if (pwd == null) throw new IllegalArgumentException("pwd cannot be null"); if (privateKeyInfo == null) throw new IllegalArgumentException("privateKeyInfo cannot be null"); if (kdfIterations < 1) kdfIterations = 2000; if (saltLen < 1) saltLen = 16; try { // generate random PBKDF2 salt SecureRandom random = new SecureRandom(); byte salt[] = new byte[saltLen]; random.nextBytes(salt); // derive symmetric key from passphrase using PBKDF2 CryptoManager cm = CryptoManager.getInstance(); CryptoToken token = cm.getInternalCryptoToken(); KeyGenerator kg = token.getKeyGenerator( PBEAlgorithm.PBE_PKCS5_PBKDF2); PBEKeyGenParams pbekgParams = new PBEKeyGenParams( pwd.getChars(), salt, kdfIterations, encAlg); if (charToByteConverter != null) kg.setCharToByteConverter(charToByteConverter); kg.initialize(pbekgParams); SymmetricKey sk = kg.generate(); // encrypt PrivateKeyInfo byte iv[] = new byte[encAlg.getBlockSize()]; random.nextBytes(iv); Cipher cipher = token.getCipherContext(encAlg); cipher.initEncrypt(sk, new IVParameterSpec(iv)); byte[] encData = cipher.doFinal(ASN1Util.encode(privateKeyInfo)); // construct KDF AlgorithmIdentifier SEQUENCE paramsKdf = new SEQUENCE(); paramsKdf.addElement(new OCTET_STRING(salt)); paramsKdf.addElement(new INTEGER(kdfIterations)); paramsKdf.addElement(new INTEGER(sk.getLength())); AlgorithmIdentifier algIdKdf = new AlgorithmIdentifier( PBEAlgorithm.PBE_PKCS5_PBKDF2.toOID(), paramsKdf); // construct encryption AlgorithmIdentifier AlgorithmIdentifier algIdEnc = new AlgorithmIdentifier( encAlg.toOID(), new OCTET_STRING(iv)); // construct "composite" PBES2 AlgorithmIdentifier SEQUENCE paramsPBES2 = new SEQUENCE(); paramsPBES2.addElement(algIdKdf); paramsPBES2.addElement(algIdEnc); AlgorithmIdentifier algIdPBES2 = new AlgorithmIdentifier( PBEAlgorithm.PBE_PKCS5_PBES2.toOID(), paramsPBES2); // construct EncryptedPrivateKeyInfo return new EncryptedPrivateKeyInfo(algIdPBES2, new OCTET_STRING(encData)); } catch (IllegalBlockSizeException e) { throw new RuntimeException("IllegalBlockSizeException in EncryptedContentInfo.createPBES2: " + e.getMessage(), e); } catch (BadPaddingException e) { throw new RuntimeException("BadPaddingException in EncryptedContentInfo.createPBES2: " + e.getMessage(), e); } } /** * Creates a new EncryptedPrivateKeyInfo, where the data is encrypted * with a password-based key- * with wrapping/unwrapping happening on token. * * @param keyGenAlg The algorithm for generating a symmetric key from * a password, salt, and iteration count. * @param password The password to use in generating the key. * @param salt The salt to use in generating the key. * @param iterationCount The number of hashing iterations to perform * while generating the key. * @param charToByteConverter The mechanism for converting the characters * in the password into bytes. If null, the default mechanism * will be used, which is UTF8. * @param pri The PrivateKey to be encrypted and stored in the * EncryptedContentInfo. */ public static EncryptedPrivateKeyInfo createPBE(PBEAlgorithm keyGenAlg, Password password, byte[] salt, int iterationCount, KeyGenerator.CharToByteConverter charToByteConverter, PrivateKey pri, CryptoToken token) throws NotInitializedException, NoSuchAlgorithmException, InvalidKeyException, InvalidAlgorithmParameterException, TokenException, CharConversionException { try { // check key gen algorithm if( ! (keyGenAlg instanceof PBEAlgorithm) ) { throw new NoSuchAlgorithmException("Key generation algorithm"+ " is not a PBE algorithm"); } PBEAlgorithm pbeAlg = keyGenAlg; // generate key KeyGenerator kg = token.getKeyGenerator( keyGenAlg ); PBEKeyGenParams pbekgParams = new PBEKeyGenParams( password, salt, iterationCount); if( charToByteConverter != null ) { kg.setCharToByteConverter( charToByteConverter ); } kg.initialize(pbekgParams); kg.temporaryKeys(true); SymmetricKey key = kg.generate(); // generate IV EncryptionAlgorithm encAlg = pbeAlg.getEncryptionAlg(); AlgorithmParameterSpec params=null; Class [] paramClasses = encAlg.getParameterClasses(); for (int i = 0; i < paramClasses.length; i ++) { if ( paramClasses[i].equals( javax.crypto.spec.IvParameterSpec.class ) ) { params = new IVParameterSpec( kg.generatePBE_IV() ); break; } } // wrap the key KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.fromOID(encAlg.toOID())); wrapper.initWrap(key, params); byte encrypted[] = wrapper.wrap(pri); // make encryption algorithm identifier PBEParameter pbeParam = new PBEParameter( salt, iterationCount ); AlgorithmIdentifier encAlgID = new AlgorithmIdentifier( keyGenAlg.toOID(), pbeParam); // create EncryptedPrivateKeyInfo EncryptedPrivateKeyInfo epki = new EncryptedPrivateKeyInfo ( encAlgID, new OCTET_STRING(encrypted) ); return epki; } catch (Exception e) { System.out.println("createPBE: exception:"+e.toString()); throw new RuntimeException("Exception in EncryptedPrivateKeyInfo" + ".createPBE: " + e.getMessage(), e); } } /** * Decrypts an EncryptedPrivateKeyInfo that was encrypted with a PBE * algorithm. The algorithm and its parameters are extracted from * the EncryptedPrivateKeyInfo. * * @param pass The password to use to generate the PBE key. * @param charToByteConverter The converter to change the password * characters to bytes. If null, the default conversion is used. */ public PrivateKeyInfo decrypt(Password pass, KeyGenerator.CharToByteConverter charToByteConverter) throws NotInitializedException, NoSuchAlgorithmException, InvalidBERException, InvalidKeyException, InvalidAlgorithmParameterException, TokenException, IllegalBlockSizeException, BadPaddingException, CharConversionException { // get the key gen parameters AlgorithmIdentifier algid = encryptionAlgorithm; KeyGenAlgorithm kgAlg = KeyGenAlgorithm.fromOID(algid.getOID()); if( !(kgAlg instanceof PBEAlgorithm)) { throw new NoSuchAlgorithmException("KeyGenAlgorithm is not a "+ "PBE algorithm"); } ASN1Value params = algid.getParameters(); if( params == null ) { throw new InvalidAlgorithmParameterException( "PBE algorithms require parameters"); } PBEParameter pbeParams; if( params instanceof PBEParameter ) { pbeParams = (PBEParameter) params; } else { byte[] encodedParams = ASN1Util.encode(params); pbeParams = (PBEParameter) ASN1Util.decode(PBEParameter.getTemplate(), encodedParams); } PBEKeyGenParams kgp = new PBEKeyGenParams(pass, pbeParams.getSalt(), pbeParams.getIterations() ); // compute the key and IV CryptoToken token = CryptoManager.getInstance().getInternalCryptoToken(); KeyGenerator kg = token.getKeyGenerator( kgAlg ); if( charToByteConverter != null ) { kg.setCharToByteConverter( charToByteConverter ); } kg.initialize(kgp); SymmetricKey key = kg.generate(); // compute algorithm parameters EncryptionAlgorithm encAlg = ((PBEAlgorithm)kgAlg).getEncryptionAlg(); AlgorithmParameterSpec algParams = null; Class [] paramClasses = encAlg.getParameterClasses(); for (int i = 0; i < paramClasses.length; i ++) { if ( paramClasses[i].equals( javax.crypto.spec.IvParameterSpec.class ) ) { algParams = new IVParameterSpec( kg.generatePBE_IV() ); break; } } // perform the decryption Cipher cipher = token.getCipherContext( encAlg ); cipher.initDecrypt(key, algParams); byte[] decrypted = Cipher.unPad( cipher.doFinal( encryptedData.toByteArray() ) ); return (PrivateKeyInfo) ASN1Util.decode(PrivateKeyInfo.getTemplate(), decrypted); } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A template class for decoding EncryptedPrivateKeyInfos from BER. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( AlgorithmIdentifier.getTemplate() ); seqt.addElement( OCTET_STRING.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new EncryptedPrivateKeyInfo( (AlgorithmIdentifier) seq.elementAt(0), (OCTET_STRING) seq.elementAt(1) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/primitive/Name.java000066400000000000000000000231711412550063600245200ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.primitive; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.CharConversionException; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.PrintableString; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * An X.500 Name. */ public class Name implements ASN1Value { SEQUENCE rdns; /** * Creates an empty Name. */ public Name() { rdns = new SEQUENCE(); } /** * Creates a name from a sequence of relative distinguished names. */ Name( SEQUENCE rdns ) { this.rdns = rdns; } /** * Adds a relative distinguished name to the Name. * * @param name A relative distinguished name (RDN) to be added to the Name. */ public void addElement( RDN name ) { rdns.addElement( name ); } /** * Adds a relative distinguished name containing a single AVA. * * @param ava An AttributeValueAssertion, which will be inserted as * the sole element of a new RDN, which will be stored in the Name. */ public void addElement( AVA ava ) { rdns.addElement( new RDN( ava ) ); } /** * Inserts the given RDN at the given index in the Name. */ public void insertElementAt( RDN name, int idx ) { rdns.insertElementAt( name, idx); } /** * Returns the RDN at the given index in the Name. */ public RDN elementAt( int idx ) { return (RDN) rdns.elementAt(idx); } /** * Removes the Name element at the given index. */ public void removeElementAt( int idx ) { rdns.removeElementAt( idx ); } /** * Returns the number of RDNs in the Name. */ public int size() { return rdns.size(); } public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { rdns.encode(ostream); } @Override public void encode(Tag implicit, OutputStream ostream) throws IOException { rdns.encode(implicit, ostream); } /** * The OID for the common name (CN) attribute. */ public static final OBJECT_IDENTIFIER commonName = new OBJECT_IDENTIFIER( new long[]{ 2, 5, 4, 3 } ); /** * The OID for the country name (C) attribute. */ public static final OBJECT_IDENTIFIER countryName = new OBJECT_IDENTIFIER( new long[]{ 2, 5, 4, 6 } ); /** * The OID for the locality name (L) attribute. */ public static final OBJECT_IDENTIFIER localityName = new OBJECT_IDENTIFIER( new long[]{ 2, 5, 4, 7 } ); /** * The OID for the state or province name (S) attribute. */ public static final OBJECT_IDENTIFIER stateOrProvinceName = new OBJECT_IDENTIFIER( new long[]{ 2, 5, 4, 8 } ); /** * The OID for the organization name (O) attribute. */ public static final OBJECT_IDENTIFIER organizationName = new OBJECT_IDENTIFIER( new long[]{ 2, 5, 4, 10 } ); /** * The OID for the organizational unit name (OU) attribute. */ public static final OBJECT_IDENTIFIER organizationalUnitName = new OBJECT_IDENTIFIER( new long[]{ 2, 5, 4, 11 } ); /** * Adds a common name (CN) to the Name. * @param CN The common name. * It will be formatted according to the IETF PKIX rules for * directory strings. */ public void addCommonName(String CN) throws CharConversionException { addElement( new AVA( commonName, new DirectoryString(CN) ) ); } /** * Adds a country name (C) to the Name. It must be exactly two characters. * @param C The country name. * It will be formatted according to the IETF PKIX rules for * directory strings. * @exception IllegalArgumentException If C.length() != 2. */ public void addCountryName(String C) throws CharConversionException { if( C.length() != 2 ) { throw new IllegalArgumentException("Country name must be exactly"+ " 2 characters"); } addElement( new AVA( countryName, new DirectoryString(C) ) ); } /** * Adds a locality name (L) to the Name. * @param L The locality name. * It will be formatted according to the IETF PKIX rules for * directory strings. */ public void addLocalityName(String L) throws CharConversionException { addElement( new AVA( localityName, new DirectoryString(L) ) ); } /** * Adds a state or province name (S) to the Name. * @param S The state or province name. * It will be formatted according to the IETF PKIX rules for * directory strings. */ public void addStateOrProvinceName(String S) throws CharConversionException { addElement( new AVA( stateOrProvinceName, new DirectoryString(S) ) ); } /** * Adds an organization name (O) to the Name. * @param O The organization name. * It will be formatted according to the IETF PKIX rules for * directory strings. */ public void addOrganizationName(String O) throws CharConversionException { addElement( new AVA( organizationName, new DirectoryString(O) ) ); } /** * Adds an organizational unit name (OU) to the Name. * @param OU The organizational unit name. * It will be formatted according to the IETF PKIX rules for * directory strings. */ public void addOrganizationalUnitName(String OU) throws CharConversionException { addElement( new AVA( organizationalUnitName, new DirectoryString(OU) ) ); } private String typeToString( OBJECT_IDENTIFIER type ) { if( type.equals(commonName) ) { return "CN"; } else if( type.equals(countryName) ) { return "C"; } else if( type.equals(localityName) ) { return "L"; } else if( type.equals(stateOrProvinceName) ) { return "S"; } else if( type.equals(organizationName) ) { return "O"; } else if( type.equals(organizationalUnitName) ) { return "OU"; } else { return null; } } private String AVAToString(AVA ava) throws InvalidBERException { OBJECT_IDENTIFIER oid = ava.getOID(); String type = typeToString( oid ); if( type == null ) { return ""; } else { return type + "=" + ava.getValue().decodeWith(DirectoryString.getTemplate()); } } public String getRFC1485() throws InvalidBERException { StringBuffer buf = new StringBuffer(80); for( int r = 0; r < rdns.size(); r++ ) { if( r > 0) { buf.append(", "); } buf.append( AVAToString( ((RDN)rdns.elementAt(r)).at(0)) ); } return buf.toString(); } private static final Name.Template templateInstance = new Name.Template(); public static Name.Template getTemplate() { return templateInstance; } public static void main(String args[]) { try { if(args.length == 0) { Name name = new Name(); OBJECT_IDENTIFIER oid; oid = new OBJECT_IDENTIFIER( new long[]{ 2, 5, 4, 10 } ); AVA ava = new AVA( oid, new PrintableString("Netscape") ); name.addElement( ava ); oid = new OBJECT_IDENTIFIER( new long[]{ 2, 5, 4, 3} ); ava = new AVA( oid, new PrintableString("moi")); name.addElement( ava ); name.encode(System.out); } else { Name.Template temp = new Name.Template(); Name name; FileInputStream fis = new FileInputStream(args[0]); try (BufferedInputStream bis = new BufferedInputStream(fis)) { name = (Name) temp.decode(bis); } System.out.println("Got name."); for( int i = 0; i < name.size(); i++ ) { AVA a = name.elementAt(i).at(0); PrintableString.Template pst = new PrintableString.Template(); PrintableString ps = (PrintableString) pst.decode( new ByteArrayInputStream( a.getValue().getEncoded() ) ); System.out.println("OID: "+a.getOID()+", String: "+ps); } System.out.println("End of name"); } } catch( Exception e) { e.printStackTrace(); } } public static class Template implements ASN1Template { @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicit, InputStream istream) throws IOException, InvalidBERException { SEQUENCE.OF_Template seqt = new SEQUENCE.OF_Template( new RDN.Template() ); SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); return new Name( seq ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/primitive/PBEParameter.java000066400000000000000000000076161412550063600261150ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.primitive; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.Tag; /** * PKCS #5 PBEParameter, and PKCS #12 pkcs-12PbeParams. The only * difference between the two is that PKCS #5 dictates that the size of the * salt must be 8 bytes, while PKCS #12 leaves the salt length undefined. * To work with both standards, this class does not check the length of the * salt but rather leaves that to the application. */ public class PBEParameter implements ASN1Value { /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private byte[] salt; private int iterations; private SEQUENCE sequence; public byte[] getSalt() { return salt; } public int getIterations() { return iterations; } /////////////////////////////////////////////////////////////////////// // constructors /////////////////////////////////////////////////////////////////////// /** * Creates a PBEParameter from a salt and iteration count. Neither * may be null. */ public PBEParameter(byte[] salt, int iterations) { this.salt = salt; this.iterations = iterations; sequence = new SEQUENCE(); sequence.addElement( new OCTET_STRING(salt) ); sequence.addElement( new INTEGER(iterations) ); } /** * Creates a PBEParameter from a salt and iteration count. Neither * may be null. */ public PBEParameter(OCTET_STRING salt, INTEGER iterations) { this( salt.toByteArray(), iterations.intValue() ); } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A template class for decoding a PBEParameter. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( OCTET_STRING.getTemplate() ); seqt.addElement( INTEGER.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new PBEParameter( (OCTET_STRING) seq.elementAt(0), (INTEGER) seq.elementAt(1) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/primitive/PrivateKeyInfo.java000066400000000000000000000133051412550063600265350ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.primitive; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.NoSuchAlgorithmException; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.SET; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.crypto.PrivateKey; public class PrivateKeyInfo implements ASN1Value, java.security.PrivateKey { private static final long serialVersionUID = 1L; /////////////////////////////////////////////////////////////////////// // members and member access /////////////////////////////////////////////////////////////////////// private INTEGER version; private AlgorithmIdentifier privateKeyAlgorithm; private OCTET_STRING privateKey; private SET attributes; // may be null private SEQUENCE sequence; public INTEGER getVersion() { return version; } public AlgorithmIdentifier getPrivateKeyAlgorithm() { return privateKeyAlgorithm; } @Override public String getAlgorithm() { try { return PrivateKey.Type.fromOID(privateKeyAlgorithm.getOID()) .toString(); } catch( NoSuchAlgorithmException e ) { return null; } } @Override public String getFormat() { return "PKCS#8"; } @Override public byte[] getEncoded() { return privateKey.toByteArray(); } public OCTET_STRING getPrivateKey() { return privateKey; } /** * May return null if no attributes are present. */ public SET getAttributes() { return attributes; } /////////////////////////////////////////////////////////////////////// // Constructors /////////////////////////////////////////////////////////////////////// /** * Create a PrivateKeyInfo from its components. * * @param attributes May be null if there are no attributes, in which * case the attributes field will be omitted from the DER encoding. * Each element must be a org.mozilla.jss.pkix.primitive.Attribute. */ public PrivateKeyInfo(INTEGER version, AlgorithmIdentifier privateKeyAlgorithm, OCTET_STRING privateKey, SET attributes) { if( version==null || privateKeyAlgorithm==null || privateKey==null ) { throw new IllegalArgumentException( "PrivateKeyInfo parameter is null"); } this.version = version; this.privateKeyAlgorithm = privateKeyAlgorithm; this.privateKey = privateKey; this.attributes = attributes; sequence = new SEQUENCE(); sequence.addElement(version); sequence.addElement(privateKeyAlgorithm); sequence.addElement(privateKey); if(attributes!=null) { sequence.addElement( new Tag(0), attributes ); // make sure all the attributes are Attributes int size = attributes.size(); for(int i=0; i < size; i++) { if( ! (attributes.elementAt(i) instanceof Attribute) ) { throw new IllegalArgumentException("element "+i+ " of attributes is not an Attribute"); } } } } /////////////////////////////////////////////////////////////////////// // DER encoding /////////////////////////////////////////////////////////////////////// private static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { sequence.encode(ostream); } @Override public void encode(Tag implicitTag, OutputStream ostream) throws IOException { sequence.encode(implicitTag, ostream); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * A template class for decoding PrivateKeyInfos from BER. */ public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( INTEGER.getTemplate() ); seqt.addElement( AlgorithmIdentifier.getTemplate() ); seqt.addElement( OCTET_STRING.getTemplate() ); seqt.addOptionalElement( new Tag(0), new SET.OF_Template( Attribute.getTemplate() ) ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws InvalidBERException, IOException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicitTag, InputStream istream) throws InvalidBERException, IOException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicitTag, istream); return new PrivateKeyInfo( (INTEGER) seq.elementAt(0), (AlgorithmIdentifier) seq.elementAt(1), (OCTET_STRING) seq.elementAt(2), (SET) seq.elementAt(3) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/primitive/RDN.java000066400000000000000000000054631412550063600242670ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.primitive; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.asn1.SET; import org.mozilla.jss.asn1.Tag; /** * A RelativeDistinguishedName, whose ASN.1 is: *
 * RelativeDistinguishedName ::= SET SIZE(1..MAX) OF AttributeValueAssertion
 * 
*/ public class RDN implements ASN1Value { private SET avas; /** * An RDN must have at least one element at all times, so an initial * element must be provided. */ public RDN(AVA initialElement) { avas = new SET(); avas.addElement(initialElement); } // This is for private use only, so we can be constructed from our // template. RDN(SET avas) { this.avas = avas; } public void add( AVA ava ) { avas.addElement( ava ); } public AVA at( int idx ) { return (AVA) avas.elementAt( idx ); } /** * @exception TooFewElementsException If removing this element would * result in the RDN being empty. */ public void removeAt( int idx ) throws TooFewElementsException { if( avas.size() <= 1 ) { throw new TooFewElementsException(); } avas.removeElementAt( idx ); } public int size() { return avas.size(); } public static final Tag TAG = SET.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { avas.encode(ostream); } @Override public void encode(Tag implicit, OutputStream ostream) throws IOException { avas.encode(implicit, ostream); } public static class Template implements ASN1Template { @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicit, InputStream istream) throws IOException, InvalidBERException { AVA.Template avatemp = new AVA.Template(); SET.OF_Template sett = new SET.OF_Template( avatemp ); SET set = (SET) sett.decode(implicit, istream); if(set.size() < 1) { throw new InvalidBERException("RDN with zero elements; "+ "an RDN must have at least one element"); } return new RDN(set); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/primitive/SubjectPublicKeyInfo.java000066400000000000000000000107401412550063600276610ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.primitive; import org.mozilla.jss.asn1.*; import java.io.InputStream; import java.io.OutputStream; import java.io.IOException; import java.security.PublicKey; import java.security.NoSuchAlgorithmException; import org.mozilla.jss.crypto.PrivateKey; import org.mozilla.jss.crypto.InvalidKeyFormatException; import org.mozilla.jss.pkcs11.PK11PubKey; /** * A SubjectPublicKeyInfo, which stores information about a public key. * This class implements java.security.PublicKey. */ public class SubjectPublicKeyInfo extends java.security.spec.X509EncodedKeySpec implements ASN1Value, java.security.PublicKey { private static final long serialVersionUID = 1L; private AlgorithmIdentifier algorithm; private BIT_STRING subjectPublicKey; @Override public String getAlgorithm() { try { return PrivateKey.Type.fromOID(algorithm.getOID()).toString(); } catch( NoSuchAlgorithmException e ) { // unknown algorithm return null; } } @Override public byte[] getEncoded() { return ASN1Util.encode(this); } public AlgorithmIdentifier getAlgorithmIdentifier() { return algorithm; } public BIT_STRING getSubjectPublicKey() { return subjectPublicKey; } private SubjectPublicKeyInfo() { super(new byte[] {0});} public SubjectPublicKeyInfo(AlgorithmIdentifier algorithm, BIT_STRING subjectPublicKey) { super( new byte[] {0} ); // super constructor can't handle null this.algorithm = algorithm; this.subjectPublicKey = subjectPublicKey; } public SubjectPublicKeyInfo(PublicKey pubk) throws InvalidBERException, IOException { super( new byte[] {0}); SubjectPublicKeyInfo spki = (SubjectPublicKeyInfo) ASN1Util.decode( getTemplate(), pubk.getEncoded() ); algorithm = spki.algorithm; subjectPublicKey = spki.subjectPublicKey; } public static final Tag TAG = SEQUENCE.TAG; @Override public Tag getTag() { return TAG; } @Override public void encode(OutputStream ostream) throws IOException { encode(TAG, ostream); } @Override public void encode(Tag implicit, OutputStream ostream) throws IOException { SEQUENCE seq = new SEQUENCE(); seq.addElement( algorithm ); seq.addElement( subjectPublicKey ); seq.encode( implicit, ostream ); } private static final Template templateInstance = new Template(); public static Template getTemplate() { return templateInstance; } /** * Creates a PublicKey from the public key information. Currently * only RSA and DSA keys can be converted. * * @exception NoSuchAlgorithmException If the cryptographic provider * does not recognize the algorithm for this public key. * @exception InvalidKeyFormatException If the subjectPublicKey could * not be decoded correctly. */ public PublicKey toPublicKey() throws NoSuchAlgorithmException, InvalidKeyFormatException { if( subjectPublicKey.getPadCount() != 0 ) { throw new InvalidKeyFormatException(); } return PK11PubKey.fromSPKI(getEncoded()); } public static class Template implements ASN1Template { private SEQUENCE.Template seqt; public Template() { seqt = new SEQUENCE.Template(); seqt.addElement( AlgorithmIdentifier.getTemplate() ); seqt.addElement( BIT_STRING.getTemplate() ); } @Override public boolean tagMatch(Tag tag) { return TAG.equals(tag); } @Override public ASN1Value decode(InputStream istream) throws IOException, InvalidBERException { return decode(TAG, istream); } @Override public ASN1Value decode(Tag implicit, InputStream istream) throws IOException, InvalidBERException { SEQUENCE seq = (SEQUENCE) seqt.decode(implicit, istream); return new SubjectPublicKeyInfo( (AlgorithmIdentifier) seq.elementAt(0), (BIT_STRING) seq.elementAt(1) ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/primitive/TooFewElementsException.java000066400000000000000000000005501412550063600304130ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.pkix.primitive; public class TooFewElementsException extends Exception { private static final long serialVersionUID = 1L; } jss-5.0.0/src/main/java/org/mozilla/jss/pkix/primitive/package.html000066400000000000000000000005261412550063600252550ustar00rootroot00000000000000 Frequently-used primitive ASN.1 types, such as AlgorithmIdentifier, PrivateKeyInfo, and X.500 Name. jss-5.0.0/src/main/java/org/mozilla/jss/provider/000077500000000000000000000000001412550063600216405ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/provider/java/000077500000000000000000000000001412550063600225615ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/provider/java/security/000077500000000000000000000000001412550063600244305ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/provider/java/security/IvAlgorithmParameters.java000066400000000000000000000040611412550063600315450ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.provider.java.security; import java.io.IOException; import java.security.AlgorithmParametersSpi; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.InvalidParameterSpecException; /** * This class is only intended to be used to implement * CipherSpi.getAlgorithmParameters(). */ public class IvAlgorithmParameters extends AlgorithmParametersSpi { private AlgorithmParameterSpec ivParamSpec; @Override public void engineInit(AlgorithmParameterSpec paramSpec) { ivParamSpec = paramSpec; } @Override public T engineGetParameterSpec(Class clazz) throws InvalidParameterSpecException { if( clazz != null && !(clazz.isInstance(ivParamSpec)) ) { Class paramSpecClass = ivParamSpec.getClass(); throw new InvalidParameterSpecException( "Mozilla-JSS IvParameter spec class error" + paramSpecClass.getName()); } return clazz.cast(ivParamSpec); } @Override public void engineInit(byte[] params) throws IOException { throw new IOException("engineInit(byte[]) not supported"); } @Override public void engineInit(byte[] params, String format) throws IOException { throw new IOException("engineInit(byte[],String) not supported"); } @Override public byte[] engineGetEncoded() throws IOException { throw new IOException("encoding IvAlgorithmParameters not supported"); } @Override public byte[] engineGetEncoded(String format) throws IOException { throw new IOException("encoding IvAlgorithmParameters not supported"); } @Override public String engineToString() { throw new RuntimeException("engineToString() not supported"); // return getClass().getName(); } } jss-5.0.0/src/main/java/org/mozilla/jss/provider/java/security/JSSKeyPairGeneratorSpi.java000066400000000000000000000045361412550063600315520ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.provider.java.security; import java.security.InvalidAlgorithmParameterException; import java.security.KeyPair; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.KeyPairAlgorithm; import org.mozilla.jss.crypto.KeyPairGenerator; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.crypto.TokenRuntimeException; import org.mozilla.jss.crypto.TokenSupplierManager; public class JSSKeyPairGeneratorSpi extends java.security.KeyPairGeneratorSpi { private KeyPairGenerator kpg; protected JSSKeyPairGeneratorSpi(KeyPairAlgorithm alg) { super(); CryptoToken token = TokenSupplierManager.getTokenSupplier().getThreadToken(); try { try { kpg = token.getKeyPairGenerator(alg); } catch(java.security.NoSuchAlgorithmException e) { throw new UnsupportedOperationException( "Token '" + token.getName() + "' does not support algorithm " + alg.toString()); } } catch(TokenException e) { throw new TokenRuntimeException(e.getMessage()); } } @Override public void initialize(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { kpg.initialize(params, random); } @Override public void initialize(int keysize, SecureRandom random) { kpg.initialize(keysize, random); } @Override public KeyPair generateKeyPair() { try { return kpg.genKeyPair(); } catch(TokenException e) { throw new TokenRuntimeException(e.getMessage()); } } public static class RSA extends JSSKeyPairGeneratorSpi { public RSA() { super(KeyPairAlgorithm.RSA); } } public static class DSA extends JSSKeyPairGeneratorSpi { public DSA() { super(KeyPairAlgorithm.DSA); } } public static class EC extends JSSKeyPairGeneratorSpi { public EC() { super(KeyPairAlgorithm.EC); } } } jss-5.0.0/src/main/java/org/mozilla/jss/provider/java/security/JSSKeyStoreSpi.c000066400000000000000000000644341412550063600274100ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "_jni/org_mozilla_jss_provider_java_security_JSSKeyStoreSpi.h" #include #include #include #include #include #include #include #include #include "java_ids.h" static PRStatus getTokenSlotPtr(JNIEnv *env, jobject keyStoreObj, PK11SlotInfo **ptr) { return JSS_getPtrFromProxyOwner(env, keyStoreObj, "proxy", "Lorg/mozilla/jss/pkcs11/TokenProxy;", (void**)ptr); } typedef enum { PRIVKEY=0x01, PUBKEY=0x02, SYMKEY=0x04, CERT=0x08 } TokenObjectType; #define ALL_OBJECT_TYPES (PRIVKEY | PUBKEY | SYMKEY | CERT ) typedef struct { PRStatus status; PRBool deleteIt; PRBool stopIterating; } JSSTraversalStatus; #define INIT_TRAVSTAT {PR_FAILURE, PR_FALSE, PR_FALSE} /* * contract: you must throw an exception if you return PRFailure. */ typedef JSSTraversalStatus (*TokenObjectTraversalCallback) (JNIEnv* env, PK11SlotInfo *slot, TokenObjectType type, void *obj, void *data); /* * objectType is bitwise-OR of all the object types you want to traverse. */ static PRStatus traverseTokenObjects (JNIEnv *env, PK11SlotInfo *slot, TokenObjectTraversalCallback cb, int objectTypes, void *data) { PRStatus status = PR_FAILURE; JSSTraversalStatus travstat = INIT_TRAVSTAT; SECKEYPrivateKeyList* privkList = NULL; SECKEYPublicKeyList* pubkList = NULL; PK11SymKey *symKey = NULL; CERTCertList *certList = NULL; /* * Get all private keys */ if( objectTypes & PRIVKEY ) { SECKEYPrivateKeyListNode *node = NULL; privkList = PK11_ListPrivKeysInSlot(slot, NULL /*nickname*/, NULL /*wincx*/); if( privkList != NULL ) { for( node = PRIVKEY_LIST_HEAD(privkList); ! PRIVKEY_LIST_END(node, privkList); node = PRIVKEY_LIST_NEXT(node) ) { travstat = cb(env, slot, PRIVKEY, (void*) node->key, data); if( travstat.status == PR_FAILURE ) { goto finish; } if( travstat.deleteIt ) { /* Setting "force" to PR_FALSE means that if there is a * matching cert, the key won't be deleted. * If the KeyStore API is being followed, the cert * should have the same nickname as the key. So * both will get deleted when we scan for matching * certs later. */ PK11_DeleteTokenPrivateKey(node->key, PR_FALSE /*force*/); node->key = NULL; PR_REMOVE_LINK(&node->links); /* we don't free node because it is allocated from * the list's arena and will get freed when the list * is freed. */ } if( travstat.stopIterating ) { goto stop_early; } } } } /* * Get all symmetric keys */ if(objectTypes & SYMKEY) { /* this function returns a chained list of symmetric keys */ symKey = PK11_ListFixedKeysInSlot(slot, NULL /*nickname*/, NULL/*wincx*/); while( symKey != NULL ) { PK11SymKey *deadKey; travstat = cb(env, slot, SYMKEY, (void*) symKey, data); if( travstat.status != PR_SUCCESS ) { goto finish; } if( travstat.deleteIt ) { /* this just deletes the PKCS #11 object. The data structure * is NOT deleted. */ PK11_DeleteTokenSymKey(symKey); } if( travstat.stopIterating ) { goto stop_early; } deadKey = symKey; symKey = PK11_GetNextSymKey(symKey); PK11_FreeSymKey(deadKey); } } /* * get all public keys */ if( objectTypes & PUBKEY ) { SECKEYPublicKeyListNode *node = NULL; pubkList = PK11_ListPublicKeysInSlot(slot, NULL /*nickname*/); if( pubkList != NULL ) { for( node = PUBKEY_LIST_HEAD(pubkList); ! PUBKEY_LIST_END(node, pubkList); node = PUBKEY_LIST_NEXT(node) ) { if( node->key == NULL ) { /* workaround NSS bug 130699: PK11_ListPublicKeysInSlot * returns NULL if slot contains token symmetric key */ continue; } travstat = cb(env, slot, PUBKEY, (void*) node->key, data); if( travstat.status != PR_SUCCESS ) { goto finish; } if( travstat.deleteIt ) { /* XXX!!! * Workaround for 125408: PK11_DeleteTokenPublic key asserts * Don't delete the public key. * PK11_DeleteTokenPublicKey(node->key); * node->key = NULL; * PR_REMOVE_LINK(&node->links); */ /* node is allocated from the list's arena, it will get * freed with the list */ } if( travstat.stopIterating ) { goto stop_early; } } /* * XXX!!! * Destroy the list before we move on. Why bother, since we'll * do it anyway in the finish block? Because of bug 125408. * If we delete the cert and private key while traversing certs, * we'll delete the public key too, and then we'll crash when * we free the same public key while destroying the list. */ SECKEY_DestroyPublicKeyList(pubkList); pubkList = NULL; } } /* * Get all certs */ if( objectTypes & CERT ) { CERTCertListNode *node = NULL; certList = PK11_ListCertsInSlot(slot); if( certList == NULL ) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to list certificates on token"); goto finish; } for( node = CERT_LIST_HEAD(certList); ! CERT_LIST_END(node, certList); node = CERT_LIST_NEXT(node) ) { travstat = cb(env, slot, CERT, (void*) node->cert, data); if( travstat.status != PR_SUCCESS ) { goto finish; } if( travstat.deleteIt ) { /* * Since, in a KeyStore, certs and private keys go together, * remove the private key too, if there is one. * * The hack here is that PK11_DeleteTokenCertAndKey will * not delete the cert if there is no matching private key. * We want to the cert to be deleted even if the key isn't * there. So we only call that function if we're sure the * key is there. Otherwise we delete the cert directly. */ SECKEYPrivateKey *privKey = PK11_FindKeyByAnyCert(node->cert, NULL /*wincx*/); PRBool keyPresent = (privKey != NULL); SECKEY_DestroyPrivateKey(privKey); if( keyPresent ) { PK11_DeleteTokenCertAndKey(node->cert, NULL /*wincx*/); } else { SEC_DeletePermCertificate(node->cert); } PR_REMOVE_LINK(&node->links); /* node is allocated from the list's arena, it will get freed * with the list */ } if( travstat.stopIterating ) { goto stop_early; } } } stop_early: status = PR_SUCCESS; finish: if( privkList != NULL ) { SECKEY_DestroyPrivateKeyList(privkList); } if( pubkList != NULL ) { SECKEY_DestroyPublicKeyList(pubkList); } while( symKey != NULL ) { PK11SymKey *deadKey; deadKey = symKey; symKey = PK11_GetNextSymKey(symKey); PK11_FreeSymKey(deadKey); } if( certList != NULL ) { CERT_DestroyCertList(certList); } return status; } /* allocates memory if type != CERT */ static char* getObjectNick(void *obj, TokenObjectType type) { switch(type) { case PRIVKEY: /* NOTE: this function allocates memory for the nickname */ return PK11_GetPrivateKeyNickname((SECKEYPrivateKey*)obj); case SYMKEY: /* NOTE: this function allocates memory for the nickname */ return PK11_GetSymKeyNickname((PK11SymKey*)obj); case PUBKEY: /* NOTE: this function allocates memory for the nickname */ return PK11_GetPublicKeyNickname((SECKEYPublicKey*)obj); case CERT: return ((CERTCertificate*)obj)->nickname; default: PR_ASSERT(PR_FALSE); return NULL; } } static void freeObjectNick(char *nick, TokenObjectType type) { if( type != CERT && nick != NULL) { PR_Free(nick); } } typedef struct { jobject setObj; jmethodID setAdd; } EngineAliasesCBInfo; static JSSTraversalStatus engineAliasesTraversalCallback (JNIEnv *env, PK11SlotInfo *slot, TokenObjectType type, void *obj, void *data) { JSSTraversalStatus travStat = INIT_TRAVSTAT; EngineAliasesCBInfo *cbinfo = (EngineAliasesCBInfo*)data; char *nickname=NULL; nickname = getObjectNick(obj, type); if( nickname != NULL ) { jstring nickString; /* convert it to a string */ nickString = (*env)->NewStringUTF(env, nickname); freeObjectNick(nickname, type); if( nickString == NULL ) { /* exception was thrown */ goto finish; } /* store the string in the vector */ (*env)->CallBooleanMethod(env, cbinfo->setObj, cbinfo->setAdd, nickString); if( (*env)->ExceptionOccurred(env) ) { goto finish; } } travStat.status = PR_SUCCESS; finish: return travStat; } JNIEXPORT jobject JNICALL Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_getRawAliases (JNIEnv *env, jobject this) { PK11SlotInfo *slot = NULL; jobject setObj=NULL; jmethodID setAdd=NULL; EngineAliasesCBInfo cbinfo; if( getTokenSlotPtr(env, this, &slot) != PR_SUCCESS ) { /* exception was thrown */ goto finish; } /* * Create the vector object and get its method IDs */ { jclass setClass; jmethodID setCons; setClass = (*env)->FindClass(env, "java/util/HashSet"); if( setClass == NULL ) { /* should have thrown an exception */ goto finish; } setCons = (*env)->GetMethodID(env, setClass, "", "()V"); if( setCons == NULL ) { goto finish; } setObj = (*env)->NewObject(env, setClass, setCons); if( setObj == NULL ) { goto finish; } setAdd = (*env)->GetMethodID(env, setClass, "add", "(Ljava/lang/Object;)Z"); if( setAdd == NULL ) { goto finish; } } cbinfo.setObj = setObj; cbinfo.setAdd = setAdd; /* * traverse all slot objects */ if( traverseTokenObjects( env, slot, engineAliasesTraversalCallback, ALL_OBJECT_TYPES, &cbinfo) != PR_SUCCESS ) { goto finish; } finish: return setObj; } typedef struct { const char *targetNickname; } EngineDeleteEntryCBInfo; static JSSTraversalStatus engineDeleteEntryTraversalCallback (JNIEnv *env, PK11SlotInfo *slot, TokenObjectType type, void *obj, void *data) { EngineDeleteEntryCBInfo *cbinfo = (EngineDeleteEntryCBInfo*)data; JSSTraversalStatus status = INIT_TRAVSTAT; char *nickname = getObjectNick(obj, type); if( nickname != NULL && (PL_strcmp(nickname, cbinfo->targetNickname) == 0) ) { status.deleteIt = PR_TRUE; } freeObjectNick(nickname, type); status.status = PR_SUCCESS; return status; } JNIEXPORT void JNICALL Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_engineDeleteEntry (JNIEnv *env, jobject this, jobject aliasString) { EngineDeleteEntryCBInfo cbinfo; PK11SlotInfo *slot = NULL; cbinfo.targetNickname = NULL; if( getTokenSlotPtr(env, this, &slot) != PR_SUCCESS ) { /* exception was thrown */ goto finish; } /* get the nickname */ cbinfo.targetNickname = JSS_RefJString(env, aliasString); if( cbinfo.targetNickname == NULL ) { goto finish; } /* traverse */ /* * traverse all slot objects */ traverseTokenObjects( env, slot, engineDeleteEntryTraversalCallback, ALL_OBJECT_TYPES, (void*) &cbinfo); finish: JSS_DerefJString(env, aliasString, cbinfo.targetNickname); } typedef struct { const char *targetNickname; CERTCertificate *cert; } EngineGetCertificateCBInfo; static JSSTraversalStatus engineGetCertificateTraversalCallback (JNIEnv *env, PK11SlotInfo *slot, TokenObjectType type, void *obj, void *data) { JSSTraversalStatus travStat = INIT_TRAVSTAT; CERTCertificate *cert = (CERTCertificate*) obj; EngineGetCertificateCBInfo *cbinfo = (EngineGetCertificateCBInfo*)data; PR_ASSERT(type == CERT); /* shouldn't get called otherwise */ PR_ASSERT(cbinfo->cert == NULL); if( cert->nickname != NULL && PL_strcmp(cert->nickname, cbinfo->targetNickname) == 0 ) { cbinfo->cert = CERT_DupCertificate(cert); travStat.stopIterating = PR_TRUE; } travStat.status = PR_SUCCESS; return travStat; } static CERTCertificate* lookupCertByNickname(JNIEnv *env, jobject this, jstring alias) { PK11SlotInfo *slot; EngineGetCertificateCBInfo cbinfo = {NULL,NULL}; PRStatus status = PR_FAILURE; if( alias == NULL ) goto finish; if( getTokenSlotPtr(env, this, &slot) != PR_SUCCESS ) { /* exception was thrown */ goto finish; } cbinfo.targetNickname = JSS_RefJString(env, alias); if(cbinfo.targetNickname == NULL ) goto finish; status = traverseTokenObjects( env, slot, engineGetCertificateTraversalCallback, CERT, (void*) &cbinfo); finish: JSS_DerefJString(env, alias, cbinfo.targetNickname); if( status != PR_SUCCESS && cbinfo.cert != NULL) { CERT_DestroyCertificate(cbinfo.cert); cbinfo.cert = NULL; } return cbinfo.cert; } JNIEXPORT jobject JNICALL Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_getCertObject (JNIEnv *env, jobject this, jstring alias) { CERTCertificate *cert = NULL; PK11SlotInfo *slot = NULL; jobject certObj = NULL; cert = lookupCertByNickname(env, this, alias); if( cert == NULL ) { goto finish; } if( getTokenSlotPtr(env, this, &slot) != PR_SUCCESS ) { /* exception was thrown */ goto finish; } slot = PK11_ReferenceSlot(slot); certObj = JSS_PK11_wrapCertAndSlot(env, &cert, &slot); finish: if( cert != NULL ) { CERT_DestroyCertificate(cert); } if( slot != NULL ) { PK11_FreeSlot(slot); } if( certObj == NULL ) { PR_ASSERT( (*env)->ExceptionOccurred(env) ); } return certObj; } JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_getDERCert (JNIEnv *env, jobject this, jstring alias) { CERTCertificate * cert = NULL; jbyteArray derCertBA = NULL; cert = lookupCertByNickname(env, this, alias); if( cert == NULL ) { goto finish; } derCertBA = JSS_SECItemToByteArray(env, &cert->derCert); finish: if( cert != NULL) { CERT_DestroyCertificate(cert); } if( derCertBA == NULL ) { PR_ASSERT( (*env)->ExceptionOccurred(env) ); } return derCertBA; } JNIEXPORT jstring JNICALL Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_getCertNickname (JNIEnv *env, jobject this, jbyteArray derCertBA) { PK11SlotInfo *slot=NULL; SECItem *derCert=NULL; CERTCertificate * cert=NULL; CERTCertificate searchCert; jstring nickString = NULL; if( getTokenSlotPtr(env, this, &slot) != PR_SUCCESS ) { /* exception was thrown */ goto finish; } /* convert derCert to SECItem */ derCert = JSS_ByteArrayToSECItem(env, derCertBA); if( derCert == NULL ) { /* exception was thrown */ goto finish; } /* lookup cert by derCert */ searchCert.derCert = *derCert; cert = PK11_FindCertFromDERCert(slot, &searchCert, NULL /*wincx*/); if( cert == NULL ) { /* not found. return NULL */ goto finish; } /* convert cert nickname to Java string */ nickString = (*env)->NewStringUTF(env, cert->nickname); finish: if( derCert != NULL ) { SECITEM_FreeItem(derCert, PR_TRUE /*freeit*/); } if( cert != NULL ) { CERT_DestroyCertificate(cert); } return nickString; } typedef struct { const char *label; SECKEYPrivateKey *privk; PK11SymKey *symk; } FindKeyCBInfo; static JSSTraversalStatus findKeyCallback (JNIEnv *env, PK11SlotInfo *slot, TokenObjectType type, void *obj, void *data) { JSSTraversalStatus status = INIT_TRAVSTAT; FindKeyCBInfo *cbinfo = (FindKeyCBInfo*)data; char *objNick = getObjectNick(obj, type); status.status = PR_SUCCESS; PR_ASSERT(cbinfo->privk==NULL && cbinfo->symk==NULL); if( PL_strcmp(objNick, cbinfo->label) == 0 ) { /* found it */ status.stopIterating = PR_TRUE; switch( type ) { case PRIVKEY: cbinfo->privk = (SECKEYPrivateKey*)obj; break; case SYMKEY: cbinfo->symk = (PK11SymKey*)obj; break; default: PR_ASSERT(PR_FALSE); status.status = PR_FAILURE; } } freeObjectNick(objNick, type); return status; } typedef struct { const char *targetNickname; SECKEYPrivateKey *privk; } GetKeyByCertNickCBInfo; static JSSTraversalStatus getKeyByCertNickCallback (JNIEnv *env, PK11SlotInfo *slot, TokenObjectType type, void *obj, void *data) { JSSTraversalStatus travStat = INIT_TRAVSTAT; CERTCertificate *cert = (CERTCertificate*) obj; GetKeyByCertNickCBInfo *cbinfo = (GetKeyByCertNickCBInfo*) data; PR_ASSERT(type == CERT); /* shouldn't get called otherwise */ PR_ASSERT(cbinfo->privk == NULL); if( cert->nickname != NULL && PL_strcmp(cert->nickname, cbinfo->targetNickname) == 0 ) { travStat.stopIterating = PR_TRUE; cbinfo->privk = PK11_FindPrivateKeyFromCert(slot, cert, NULL /*wincx*/); if( cbinfo->privk ) { printf("Found private key from cert with label '%s'\n", cert->nickname); } } travStat.status = PR_SUCCESS; return travStat; } /* * This is only here for backward compatibility. */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_engineGetKey (JNIEnv *env, jobject this, jstring alias, jcharArray password) { PR_ASSERT(0); JSS_throwMsg(env, "java/lang/RuntimeException", "Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_engine" "GetKey not implemented"); return NULL; } JNIEXPORT jobject JNICALL Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_engineGetKeyNative (JNIEnv *env, jobject this, jstring alias, jcharArray password) { PK11SlotInfo *slot=NULL; FindKeyCBInfo keyCbinfo = {NULL, NULL, NULL}; GetKeyByCertNickCBInfo certCbinfo = {NULL, NULL}; jobject keyObj = NULL; if( getTokenSlotPtr(env, this, &slot) != PR_SUCCESS ) { /* exception was thrown */ goto finish; } if( alias == NULL ) { goto finish; } /* * first look for a matching key */ keyCbinfo.label = JSS_RefJString(env, alias); if( keyCbinfo.label == NULL ) { goto finish; } if( traverseTokenObjects( env, slot, findKeyCallback, PRIVKEY | SYMKEY, &keyCbinfo) != PR_SUCCESS ) { goto finish; } if(keyCbinfo.privk != NULL ) { /* found a matching private key */ keyObj = JSS_PK11_wrapPrivKey(env, &keyCbinfo.privk); } else if( keyCbinfo.symk != NULL ) { /* found a matching symmetric key */ keyObj = JSS_PK11_wrapSymKey(env, &keyCbinfo.symk); } if( keyObj == NULL ) { /* * If we didn't find a matching key, look for a matching cert */ certCbinfo.targetNickname = JSS_RefJString(env, alias); if(certCbinfo.targetNickname == NULL ) goto finish; if( traverseTokenObjects( env, slot, getKeyByCertNickCallback, CERT, (void*) &certCbinfo) != PR_SUCCESS ) { goto finish; } if( certCbinfo.privk != NULL ) { keyObj = JSS_PK11_wrapPrivKey(env, &certCbinfo.privk); } } finish: JSS_DerefJString(env, alias, keyCbinfo.label); JSS_DerefJString(env, alias, certCbinfo.targetNickname); PR_ASSERT( keyCbinfo.privk==NULL && keyCbinfo.symk==NULL); PR_ASSERT( certCbinfo.privk==NULL ); return keyObj; } JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_engineIsCertificateEntry (JNIEnv *env, jobject this, jstring alias) { PK11SlotInfo *slot; EngineGetCertificateCBInfo cbinfo = {NULL,NULL}; jboolean retVal = JNI_FALSE; if( alias == NULL ) goto finish; if( getTokenSlotPtr(env, this, &slot) != PR_SUCCESS ) { /* exception was thrown */ goto finish; } cbinfo.targetNickname = JSS_RefJString(env, alias); if(cbinfo.targetNickname == NULL ) goto finish; if( traverseTokenObjects( env, slot, engineGetCertificateTraversalCallback, CERT, (void*) &cbinfo) != PR_SUCCESS ) { goto finish; } if( cbinfo.cert != NULL ) { unsigned int allTrust; CERTCertTrust trust; SECStatus status; status = CERT_GetCertTrust(cbinfo.cert, &trust); if( status != SECSuccess ) { goto finish; } allTrust = trust.sslFlags | trust.emailFlags | trust.objectSigningFlags; if( (allTrust & (CERTDB_TRUSTED | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA)) && !(allTrust & CERTDB_USER) ) { /* It's a trusted cert and not a user cert. */ retVal = JNI_TRUE; } } finish: JSS_DerefJString(env, alias, cbinfo.targetNickname); if( cbinfo.cert != NULL) { CERT_DestroyCertificate(cbinfo.cert); } return retVal; } JNIEXPORT void JNICALL Java_org_mozilla_jss_provider_java_security_JSSKeyStoreSpi_engineSetKeyEntryNative (JNIEnv *env, jobject this, jstring alias, jobject keyObj, jcharArray password, jobjectArray certChain) { jclass privkClass, symkClass; const char *nickname = NULL; SECKEYPrivateKey *tokenPrivk=NULL; PK11SymKey *tokenSymk=NULL; if( keyObj==NULL || alias==NULL) { JSS_throw(env, NULL_POINTER_EXCEPTION); goto finish; } nickname = JSS_RefJString(env, alias); if( nickname == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } privkClass = (*env)->FindClass(env, PK11PRIVKEY_CLASS_NAME); symkClass = (*env)->FindClass(env, PK11SYMKEY_CLASS_NAME); if( privkClass==NULL || symkClass==NULL) { ASSERT_OUTOFMEM(env); goto finish; } if( (*env)->IsInstanceOf(env, keyObj, privkClass) ) { SECKEYPrivateKey *privk; if( JSS_PK11_getPrivKeyPtr(env, keyObj, &privk) != PR_SUCCESS ) { JSS_throwMsgPrErr(env, KEYSTORE_EXCEPTION, "Failed to extract NSS key from private key object"); goto finish; } tokenPrivk = PK11_ConvertSessionPrivKeyToTokenPrivKey(privk, NULL); if( tokenPrivk == NULL ) { JSS_throwMsgPrErr(env, KEYSTORE_EXCEPTION, "Failed to copy private key to permanent token object"); goto finish; } if( PK11_SetPrivateKeyNickname(tokenPrivk, nickname) != SECSuccess ) { JSS_throwMsgPrErr(env, KEYSTORE_EXCEPTION, "Failed to set alias of copied private key"); goto finish; } } else if( (*env)->IsInstanceOf(env, keyObj, symkClass) ) { PK11SymKey *symk; if( JSS_PK11_getSymKeyPtr(env, keyObj, &symk) != PR_SUCCESS ) { JSS_throwMsgPrErr(env, KEYSTORE_EXCEPTION, "Failed to extract NSS key from symmetric key object"); goto finish; } tokenSymk = PK11_ConvertSessionSymKeyToTokenSymKey(symk, NULL); if( tokenSymk == NULL ) { JSS_throwMsgPrErr(env, KEYSTORE_EXCEPTION, "Failed to copy symmetric key to permanent token object"); goto finish; } if( PK11_SetSymKeyNickname(tokenSymk, nickname) != SECSuccess ) { JSS_throwMsgPrErr(env, KEYSTORE_EXCEPTION, "Failed to set alias of symmetric key"); goto finish; } } else { JSS_throwMsg(env, KEYSTORE_EXCEPTION, "Unrecognized key type: must be JSS private key (PK11PrivKey) or" " JSS symmetric key (PK11SymKey)"); goto finish; } finish: JSS_DerefJString(env, alias, nickname); if( tokenPrivk != NULL ) { SECKEY_DestroyPrivateKey(tokenPrivk); } if( tokenSymk != NULL ) { PK11_FreeSymKey(tokenSymk); } } jss-5.0.0/src/main/java/org/mozilla/jss/provider/java/security/JSSKeyStoreSpi.java000066400000000000000000000477241412550063600301120ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.provider.java.security; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.security.Key; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.PublicKey; import java.security.cert.Certificate; import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Enumeration; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import org.apache.commons.lang3.StringUtils; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NoSuchTokenException; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.crypto.CryptoStore; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.NoSuchItemOnTokenException; import org.mozilla.jss.crypto.ObjectNotFoundException; import org.mozilla.jss.crypto.PrivateKey; import org.mozilla.jss.crypto.SecretKeyFacade; import org.mozilla.jss.crypto.SymmetricKey; import org.mozilla.jss.crypto.TokenCertificate; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.crypto.TokenSupplierManager; import org.mozilla.jss.crypto.X509Certificate; import org.mozilla.jss.netscape.security.util.Utils; import org.mozilla.jss.pkcs11.PK11Token; import org.mozilla.jss.pkcs11.PK11Cert; import org.mozilla.jss.pkcs11.TokenProxy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * The JSS implementation of the JCA KeyStore SPI. * *

Implementation notes *

    *
  1. deleteEntry will delete all entries with that label. If the entry is a * cert with a matching private key, it will also delete the private key. * *
  2. getCertificate returns first cert with matching nickname. Returns it as * a PK11Cert, when possible. * *
  3. getCreationDate is unsupported because NSS doesn't store that * information. * *
  4. getKey first looks for a private/symmetric key with the given label. * It returns the first one it finds. If it doesn't find one, it looks for a * cert with the given nickname. If it finds one, it returns the private key * for that cert. * *
  5. isCertificateEntry returns true if there is a cert with this nickname, * but it doesn't have a private key. isKeyEntry returns true if there is a key * with this nickname, or if there is a cert with this nickname and the cert * has an associated private key. * *
  6. load updates the token in the keystore. * *
  7. store is a no-op. * *
  8. setCertificateEntry doesn't work.NSS doesn't have a way of storing a * certificate on a specific token unless it has an associated private key. * That rules out trusted certificate entries. * *
  9. setKeyEntry not supported yet. Need to convert a temporary key * into a permanent key. *
*/ public class JSSKeyStoreSpi extends java.security.KeyStoreSpi { public static Logger logger = LoggerFactory.getLogger(JSSKeyStoreSpi.class); CryptoToken token; protected TokenProxy proxy; public JSSKeyStoreSpi() { logger.debug("JSSKeyStoreSpi: ()"); CryptoToken token = TokenSupplierManager.getTokenSupplier().getThreadToken(); PK11Token pk11tok = (PK11Token)token; proxy = pk11tok.getProxy(); } String[] parseAlias(String alias) { String tokenName; String nickname; String[] parts = StringUtils.splitPreserveAllTokens(alias, ':'); if (parts.length == 1) { tokenName = null; nickname = parts[0]; } else if (parts.length == 2) { tokenName = StringUtils.defaultIfEmpty(parts[0], null); nickname = parts[1]; } else { throw new RuntimeException("Invalid alias: " + alias); } logger.debug("JSSKeyStoreSpi: token: " + tokenName); logger.debug("JSSKeyStoreSpi: nickname: " + nickname); return new String[] { tokenName, nickname }; } @Override public Enumeration engineAliases() { logger.debug("JSSKeyStoreSpi: engineAliases()"); return Collections.enumeration(getAliases()); } public Collection getAliases() { logger.debug("JSSKeyStoreSpi: getAliases()"); Set aliases = new LinkedHashSet<>(); try { List tokens = new ArrayList<>(); CryptoManager cm = CryptoManager.getInstance(); if (token == null) { logger.debug("JSSKeyStoreSpi: getting aliases from all tokens"); Enumeration e = cm.getAllTokens(); while (e.hasMoreElements()) { CryptoToken t = e.nextElement(); if (t == cm.getInternalCryptoToken()) { continue; // exclude crypto token } tokens.add(t); } } else { logger.debug("JSSKeyStoreSpi: getting aliases from keystore token"); tokens.add(token); } for (CryptoToken token : tokens) { String tokenName; if (token == cm.getInternalKeyStorageToken()) { tokenName = null; logger.debug("JSSKeyStoreSpi: token: internal"); } else { tokenName = token.getName(); logger.debug("JSSKeyStoreSpi: token: " + tokenName); } CryptoStore store = token.getCryptoStore(); logger.debug("JSSKeyStoreSpi: - certificates:"); for (X509Certificate cert : store.getCertificates()) { String nickname = cert.getNickname(); logger.debug("JSSKeyStoreSpi: - " + nickname); aliases.add(nickname); } logger.debug("JSSKeyStoreSpi: - private keys:"); for (PrivateKey privateKey : store.getPrivateKeys()) { // convert key ID into hexadecimal String keyID = Utils.HexEncode(privateKey.getUniqueID()); String nickname; if (tokenName == null) { nickname = keyID; } else { nickname = tokenName + ":" + keyID; } logger.debug("JSSKeyStoreSpi: - " + nickname); aliases.add(nickname); } } return aliases; } catch (NotInitializedException e) { throw new RuntimeException(e); } catch (TokenException e) { throw new RuntimeException(e); } } @Override public boolean engineContainsAlias(String alias) { logger.debug("JSSKeyStoreSpi: engineContainsAlias(" + alias + ")"); return getAliases().contains(alias); } @Override public void engineDeleteEntry(String alias) throws KeyStoreException { try { CryptoManager manager = CryptoManager.getInstance(); try { logger.debug("JSSKeyStoreSpi: searching for cert"); X509Certificate cert = manager.findCertByNickname(alias); CryptoToken token; if (cert instanceof TokenCertificate) { TokenCertificate tokenCert = (TokenCertificate) cert; token = tokenCert.getOwningToken(); } else { token = manager.getInternalKeyStorageToken(); } CryptoStore store = token.getCryptoStore(); logger.debug("JSSKeyStoreSpi: deleting cert: " + alias); store.deleteCertOnly(cert); return; } catch (ObjectNotFoundException e) { logger.debug("JSSKeyStoreSpi: cert not found, searching for key"); } String[] parts = parseAlias(alias); String tokenName = parts[0]; String nickname = parts[1]; CryptoToken token; if (tokenName == null) { token = manager.getInternalKeyStorageToken(); } else { token = manager.getTokenByName(tokenName); } CryptoStore store = token.getCryptoStore(); logger.debug("JSSKeyStoreSpi: searching for private key"); for (PrivateKey privateKey : store.getPrivateKeys()) { // convert key ID into hexadecimal String keyID = Utils.HexEncode(privateKey.getUniqueID()); logger.debug("JSSKeyStoreSpi: - " + keyID); if (!nickname.equals(keyID)) { continue; } try { logger.debug("JSSKeyStoreSpi: searching for public key: " + nickname); PublicKey publicKey = store.findPublicKey(privateKey); logger.debug("JSSKeyStoreSpi: deleting public key: " + nickname); store.deletePublicKey(publicKey); } catch (ObjectNotFoundException e) { logger.debug("JSSKeyStoreSpi: public key not found: " + nickname); } logger.debug("JSSKeyStoreSpi: deleting private key: " + nickname); store.deletePrivateKey(privateKey); return; } logger.debug("JSSKeyStoreSpi: entry not found: " + alias); throw new KeyStoreException("Entry not found: " + alias); } catch (NotInitializedException e) { throw new KeyStoreException(e); } catch (NoSuchTokenException e) { throw new KeyStoreException(e); } catch (TokenException e) { throw new KeyStoreException(e); } catch (NoSuchItemOnTokenException e) { throw new KeyStoreException(e); } } @Override public Certificate engineGetCertificate(String alias) { logger.debug("JSSKeyStoreSpi: engineGetCertificate(" + alias + ")"); try { CryptoManager cm = CryptoManager.getInstance(); X509Certificate cert = cm.findCertByNickname(alias); logger.debug("JSSKeyStoreSpi: cert found: " + alias); if (cert instanceof PK11Cert) { return (PK11Cert) cert; } byte[] bytes = cert.getEncoded(); InputStream is = new ByteArrayInputStream(bytes); CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); return certFactory.generateCertificate(is); } catch (ObjectNotFoundException e) { logger.debug("JSSKeyStoreSpi: cert not found: " + alias); return null; } catch (NotInitializedException e) { throw new RuntimeException(e); } catch (TokenException e) { throw new RuntimeException(e); } catch (CertificateEncodingException e) { throw new RuntimeException(e); } catch (CertificateException e) { throw new RuntimeException(e); } } @Override public String engineGetCertificateAlias(Certificate cert) { logger.debug("JSSKeyStoreSpi: engineGetCertificateAlias()"); try { if (cert instanceof PK11Cert) { PK11Cert _c = (PK11Cert) cert; return _c.getNickname(); } return getCertNickname( cert.getEncoded() ); } catch(CertificateEncodingException e) { return null; } } private native String getCertNickname(byte[] derCert); @Override public Certificate[] engineGetCertificateChain(String alias) { logger.debug("JSSKeyStoreSpi: engineGetCertificateChain(" + alias + ")"); try { logger.debug("JSSKeyStoreSpi: searching for leaf cert"); CryptoManager cm = CryptoManager.getInstance(); X509Certificate leaf = cm.findCertByNickname(alias); logger.debug("JSSKeyStoreSpi: building cert chain"); X509Certificate[] certs = cm.buildCertificateChain(leaf); Certificate[] chain = new Certificate[certs.length]; CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); for (int i = 0; i < certs.length; i++) { X509Certificate cert = certs[i]; logger.debug("JSSKeyStoreSpi: - " + cert.getSubjectDN()); if (cert instanceof PK11Cert) { chain[i] = (PK11Cert) cert; continue; } byte[] bytes = cert.getEncoded(); InputStream is = new ByteArrayInputStream(bytes); chain[i] = certFactory.generateCertificate(is); } return chain; } catch (ObjectNotFoundException e) { logger.debug("leaf cert not found: " + alias); return null; } catch (NotInitializedException e) { throw new RuntimeException(e); } catch (TokenException e) { throw new RuntimeException(e); } catch (CertificateException e) { throw new RuntimeException(e); } } /* * Not supported. */ @Override public java.util.Date engineGetCreationDate(String alias) { logger.debug("JSSKeyStoreSpi: engineGetCreationDate(" + alias + ")"); return null; } @Override public Key engineGetKey(String alias, char[] password) { logger.debug("JSSKeyStoreSpi: engineGetKey(" + alias + ")"); try { CryptoManager cm = CryptoManager.getInstance(); logger.debug("JSSKeyStoreSpi: searching for cert"); try { X509Certificate cert = cm.findCertByNickname(alias); logger.debug("JSSKeyStoreSpi: found cert: " + alias); PrivateKey privateKey = cm.findPrivKeyByCert(cert); logger.debug("JSSKeyStoreSpi: found private key: " + alias); return privateKey; } catch (ObjectNotFoundException e) { logger.debug("JSSKeyStoreSpi: cert/key not found, searching for key"); } String[] parts = parseAlias(alias); String tokenName = parts[0]; String nickname = parts[1]; CryptoToken token; if (tokenName == null) { token = cm.getInternalKeyStorageToken(); } else { token = cm.getTokenByName(tokenName); } CryptoStore store = token.getCryptoStore(); logger.debug("JSSKeyStoreSpi: searching for private key"); for (PrivateKey privateKey : store.getPrivateKeys()) { // convert key ID into hexadecimal String keyID = Utils.HexEncode(privateKey.getUniqueID()); logger.debug("JSSKeyStoreSpi: - " + keyID); if (nickname.equals(keyID)) { logger.debug("JSSKeyStoreSpi: found private key: " + nickname); return privateKey; } } logger.debug("JSSKeyStoreSpi: searching for symmetric key"); for (SymmetricKey symmetricKey : store.getSymmetricKeys()) { logger.debug("JSSKeyStoreSpi: - " + symmetricKey.getNickName()); if (nickname.equals(symmetricKey.getNickName())) { logger.debug("JSSKeyStoreSpi: found symmetric key: " + nickname); return new SecretKeyFacade(symmetricKey); } } logger.debug("JSSKeyStoreSpi: key not found: " + nickname); return null; } catch (NoSuchTokenException e) { throw new RuntimeException(e); } catch (NotInitializedException e) { throw new RuntimeException(e); } catch (TokenException e) { throw new RuntimeException(e); } } /** * Returns true if there is a cert with this nickname but there is no * key associated with the cert. */ @Override public boolean engineIsCertificateEntry(String alias) { logger.debug("JSSKeyStoreSpi: engineIsCertificateEntry(" + alias + ")"); try { CryptoManager cm = CryptoManager.getInstance(); cm.findCertByNickname(alias); logger.debug("JSSKeyStoreSpi: cert found: " + alias); return true; } catch (ObjectNotFoundException e) { logger.debug("JSSKeyStoreSpi: cert not found: " + alias); return false; } catch (NotInitializedException e) { throw new RuntimeException(e); } catch (TokenException e) { throw new RuntimeException(e); } } /** * Returns true if there is a key with this alias, or if * there is a cert with this alias that has an associated key. */ @Override public boolean engineIsKeyEntry(String alias) { logger.debug("JSSKeyStoreSpi: engineIsKeyEntry(" + alias + ")"); /* this is somewhat wasteful but we can speed it up later */ return engineGetKey(alias, null) != null; } @Override public void engineLoad(InputStream stream, char[] password) throws IOException { logger.debug("JSSKeyStoreSpi: engineLoad(stream, password)"); } @Override public void engineLoad(KeyStore.LoadStoreParameter param) throws IOException { logger.debug("JSSKeyStoreSpi: engineLoad(param)"); if (!(param instanceof JSSLoadStoreParameter)) { throw new IOException("Invalid keystore parameter type: " + param.getClass().getName()); } JSSLoadStoreParameter jssParam = (JSSLoadStoreParameter) param; token = jssParam.getToken(); try { logger.debug("JSSKeyStoreSpi: token: " + token.getName()); } catch (TokenException e) { throw new IOException(e); } } /** * NSS doesn't have a way of storing a certificate on a specific token * unless it has an associated private key. That rules out * trusted certificate entries, so we can't supply this method currently. */ @Override public void engineSetCertificateEntry(String alias, Certificate cert) throws KeyStoreException { logger.debug("JSSKeyStoreSpi: engineSetCertificateEntry(" + alias + ")"); throw new KeyStoreException( "Storing trusted certificate entries to a JSS KeyStore is not" + " supported."); } @Override public void engineSetKeyEntry(String alias, byte[] key, Certificate[] chain) throws KeyStoreException { logger.debug("JSSKeyStoreSpi: engineSetKeyEntry(" + alias + ", key, chain)"); throw new KeyStoreException("Storing plaintext keys is not supported."+ "Store the key as a handle instead."); } @Override public void engineSetKeyEntry(String alias, Key key, char[] password, Certificate[] chain) throws KeyStoreException { logger.debug("JSSKeyStoreSpi: engineSetKeyEntry(" + alias + ", key, password, chain)"); if( key instanceof SecretKeyFacade ) { SecretKeyFacade skf = (SecretKeyFacade)key; engineSetKeyEntryNative(alias, skf.key, password, chain); } else { engineSetKeyEntryNative(alias, key, password, chain); } } private native void engineSetKeyEntryNative(String alias, Object key, char[] password, Certificate[] chain) throws KeyStoreException; @Override public int engineSize() { logger.debug("JSSKeyStoreSpi: engineSize()"); return getAliases().size(); } @Override public void engineStore(OutputStream stream, char[] password) throws IOException { logger.debug("JSSKeyStoreSpi: engineStore()"); } } jss-5.0.0/src/main/java/org/mozilla/jss/provider/java/security/JSSLoadStoreParameter.java000066400000000000000000000013541412550063600314130ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.provider.java.security; import java.security.KeyStore.LoadStoreParameter; import java.security.KeyStore.ProtectionParameter; import org.mozilla.jss.crypto.CryptoToken; public class JSSLoadStoreParameter implements LoadStoreParameter { CryptoToken token; public JSSLoadStoreParameter(CryptoToken token) { this.token = token; } @Override public ProtectionParameter getProtectionParameter() { return null; } public CryptoToken getToken() { return token; } } jss-5.0.0/src/main/java/org/mozilla/jss/provider/java/security/JSSMessageDigestSpi.java000066400000000000000000000100371412550063600310540ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.provider.java.security; import java.security.DigestException; import java.security.MessageDigestSpi; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.DigestAlgorithm; import org.mozilla.jss.crypto.JSSMessageDigest; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.crypto.TokenRuntimeException; import org.mozilla.jss.crypto.TokenSupplierManager; public abstract class JSSMessageDigestSpi extends MessageDigestSpi { private JSSMessageDigest digest; protected JSSMessageDigestSpi(DigestAlgorithm alg) { super(); CryptoToken token = TokenSupplierManager.getTokenSupplier().getThreadToken(); try { CryptoManager cm = CryptoManager.getInstance(); CryptoToken ikst = cm.getInternalKeyStorageToken(); if( token.equals(ikst) ) { // InternalKeyStorageToken doesn't support message digesting token = cm.getInternalCryptoToken(); } try { digest = token.getDigestContext(alg); } catch(java.security.NoSuchAlgorithmException e) { throw new UnsupportedOperationException( "Token '" + token.getName() + "' does not support " + "algorithm " + alg.toString()); } } catch(TokenException e) { throw new TokenRuntimeException(e.getMessage()); } catch(DigestException e1) { throw new TokenRuntimeException(e1.getMessage()); } catch(NotInitializedException e2) { throw new TokenRuntimeException(e2.getMessage()); } } @Override public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } @Override public byte[] engineDigest() { try { return digest.digest(); } catch(java.security.DigestException de) { throw new TokenRuntimeException(de.getMessage()); } } @Override public int engineDigest(byte[] buf, int offset, int len) throws DigestException { return digest.digest(buf, offset, len); } @Override public int engineGetDigestLength() { return digest.getOutputSize(); } @Override public void engineReset() { try { digest.reset(); } catch(java.security.DigestException de) { throw new TokenRuntimeException(de.getMessage()); } } @Override public void engineUpdate(byte input) { try { digest.update(input); } catch(java.security.DigestException de) { throw new TokenRuntimeException(de.getMessage()); } } @Override public void engineUpdate(byte[] input, int offset, int len) { try { digest.update(input,offset,len); } catch(java.security.DigestException de) { throw new TokenRuntimeException(de.getMessage()); } } public static class SHA1 extends JSSMessageDigestSpi { public SHA1() { super( DigestAlgorithm.SHA1 ); } } public static class SHA256 extends JSSMessageDigestSpi { public SHA256() { super( DigestAlgorithm.SHA256 ); } } public static class SHA384 extends JSSMessageDigestSpi { public SHA384() { super( DigestAlgorithm.SHA384 ); } } public static class SHA512 extends JSSMessageDigestSpi { public SHA512() { super( DigestAlgorithm.SHA512 ); } } public static class MD5 extends JSSMessageDigestSpi { public MD5() { super( DigestAlgorithm.MD5 ); } } public static class MD2 extends JSSMessageDigestSpi { public MD2() { super( DigestAlgorithm.MD2 ); } } } jss-5.0.0/src/main/java/org/mozilla/jss/provider/java/security/JSSSecureRandomSpi.java000066400000000000000000000020111412550063600307100ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.provider.java.security; import org.mozilla.jss.crypto.TokenSupplierManager; import org.mozilla.jss.crypto.JSSSecureRandom; public class JSSSecureRandomSpi extends java.security.SecureRandomSpi { private static final long serialVersionUID = 1L; JSSSecureRandom engine; public JSSSecureRandomSpi() { super(); engine = TokenSupplierManager.getTokenSupplier().getSecureRNG(); } @Override protected byte[] engineGenerateSeed(int numBytes) { byte[] bytes = new byte[numBytes]; engine.nextBytes(bytes); return bytes; } @Override protected void engineNextBytes(byte[] bytes) { engine.nextBytes(bytes); } @Override protected void engineSetSeed(byte[] seed) { engine.setSeed(seed); } } jss-5.0.0/src/main/java/org/mozilla/jss/provider/java/security/JSSSignatureSpi.java000066400000000000000000000215041412550063600302720ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.provider.java.security; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.InvalidParameterException; import java.security.KeyFactory; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PublicKey; import java.security.SecureRandom; import java.security.SignatureException; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.X509EncodedKeySpec; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.PrivateKey; import org.mozilla.jss.crypto.SignatureAlgorithm; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.crypto.TokenSupplierManager; public class JSSSignatureSpi extends java.security.SignatureSpi { org.mozilla.jss.crypto.Signature sig; SignatureAlgorithm alg; AlgorithmParameterSpec paramSpec; protected JSSSignatureSpi(SignatureAlgorithm alg) { this.alg = alg; } @Override public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } @Override public void engineInitSign(java.security.PrivateKey privateKey, SecureRandom random) throws InvalidKeyException { // discard the random engineInitSign(privateKey); } @Override public void engineInitSign(java.security.PrivateKey privateKey) throws InvalidKeyException { try { sig = getSigContext(privateKey); if (paramSpec != null) { sig.setParameter(paramSpec); } sig.initSign((PrivateKey)privateKey); } catch(java.security.NoSuchAlgorithmException e) { throw new InvalidKeyException("Algorithm not supported: " + e.getMessage(), e); } catch(TokenException e) { throw new InvalidKeyException("Token exception occurred: " + e.getMessage(), e); } catch(InvalidAlgorithmParameterException e) { throw new InvalidKeyException("AlgorithmParameterSpec not supported: " + e.getMessage(), e); } } private org.mozilla.jss.crypto.Signature getSigContext(java.security.PrivateKey privateKey) throws NoSuchAlgorithmException, InvalidKeyException, TokenException { CryptoToken token; PrivateKey privk; if( ! (privateKey instanceof PrivateKey) ) { throw new InvalidKeyException(); } privk = (PrivateKey)privateKey; token = privk.getOwningToken(); return token.getSignatureContext(alg); } @Override public void engineInitVerify(PublicKey publicKey) throws InvalidKeyException { try { CryptoToken token = TokenSupplierManager.getTokenSupplier().getThreadToken(); sig = token.getSignatureContext(alg); // convert the public key into a JSS public key if necessary if( ! (publicKey instanceof org.mozilla.jss.pkcs11.PK11PubKey) ) { if( ! publicKey.getFormat().equalsIgnoreCase("X.509") ) { throw new InvalidKeyException( "Unsupported public key format: " + publicKey.getFormat()); } X509EncodedKeySpec encodedKey = new X509EncodedKeySpec(publicKey.getEncoded()); KeyFactory fact = KeyFactory.getInstance( publicKey.getAlgorithm(), "Mozilla-JSS"); publicKey = fact.generatePublic(encodedKey); } sig.initVerify(publicKey); } catch(NoSuchProviderException e) { throw new InvalidKeyException("Unable to convert non-JSS key " + "to JSS key"); } catch(java.security.spec.InvalidKeySpecException e) { throw new InvalidKeyException("Unable to convert non-JSS key " + "to JSS key"); } catch(java.security.NoSuchAlgorithmException e) { throw new InvalidKeyException("Algorithm not supported"); } catch(TokenException e) { throw new InvalidKeyException("Token exception occurred"); } } @Override public void engineUpdate(byte b) throws SignatureException { try { sig.update(b); } catch( TokenException e) { throw new SignatureException("TokenException: "+e.toString()); } } @Override public void engineUpdate(byte[] b, int off, int len) throws SignatureException { try { sig.update(b, off, len); } catch( TokenException e) { throw new SignatureException("TokenException: "+e.toString()); } } @Override public byte[] engineSign() throws SignatureException { try { return sig.sign(); } catch(TokenException e) { throw new SignatureException("TokenException: "+e.toString()); } } @Override public int engineSign(byte[] outbuf, int offset, int len) throws SignatureException { try { return sig.sign(outbuf, offset, len); } catch(TokenException e) { throw new SignatureException("TokenException: "+e.toString()); } } @Override public boolean engineVerify(byte[] sigBytes) throws SignatureException { try { return sig.verify(sigBytes); } catch( TokenException e) { throw new SignatureException("TokenException: "+e.toString()); } } @Override public void engineSetParameter(AlgorithmParameterSpec params) throws InvalidAlgorithmParameterException { paramSpec = params; } @Override public Object engineGetParameter(String param) throws InvalidParameterException { throw new InvalidParameterException( "name/value parameters not supported"); } @Override public void engineSetParameter(String param, Object value) throws InvalidParameterException { throw new InvalidParameterException( "name/value parameters not supported"); } public static class DSA extends JSSSignatureSpi { public DSA() { super(SignatureAlgorithm.DSASignatureWithSHA1Digest); } } public static class SHA1EC extends JSSSignatureSpi { public SHA1EC() { super(SignatureAlgorithm.ECSignatureWithSHA1Digest); } } public static class SHA256EC extends JSSSignatureSpi { public SHA256EC() { super(SignatureAlgorithm.ECSignatureWithSHA256Digest); } } public static class SHA384EC extends JSSSignatureSpi { public SHA384EC() { super(SignatureAlgorithm.ECSignatureWithSHA384Digest); } } public static class SHA512EC extends JSSSignatureSpi { public SHA512EC() { super(SignatureAlgorithm.ECSignatureWithSHA512Digest); } } public static class MD2RSA extends JSSSignatureSpi { public MD2RSA() { super(SignatureAlgorithm.RSASignatureWithMD2Digest); } } public static class MD5RSA extends JSSSignatureSpi { public MD5RSA() { super(SignatureAlgorithm.RSASignatureWithMD5Digest); } } public static class SHA1RSA extends JSSSignatureSpi { public SHA1RSA() { super(SignatureAlgorithm.RSASignatureWithSHA1Digest); } } public static class SHA256RSA extends JSSSignatureSpi { public SHA256RSA() { super(SignatureAlgorithm.RSASignatureWithSHA256Digest); } } public static class SHA384RSA extends JSSSignatureSpi { public SHA384RSA() { super(SignatureAlgorithm.RSASignatureWithSHA384Digest); } } public static class SHA512RSA extends JSSSignatureSpi { public SHA512RSA() { super(SignatureAlgorithm.RSASignatureWithSHA512Digest); } } public static class RSAPSSSignature extends JSSSignatureSpi { public RSAPSSSignature() { super(SignatureAlgorithm.RSAPSSSignature); } } public static class SHA256RSAPSS extends JSSSignatureSpi { public SHA256RSAPSS() { super(SignatureAlgorithm.RSAPSSSignatureWithSHA256Digest); } } public static class SHA384RSAPSS extends JSSSignatureSpi { public SHA384RSAPSS() { super(SignatureAlgorithm.RSAPSSSignatureWithSHA384Digest); } } public static class SHA512RSAPSS extends JSSSignatureSpi { public SHA512RSAPSS() { super(SignatureAlgorithm.RSAPSSSignatureWithSHA512Digest); } } } jss-5.0.0/src/main/java/org/mozilla/jss/provider/java/security/KeyFactorySpi1_2.java000066400000000000000000000257431412550063600303440ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.provider.java.security; import java.io.PrintWriter; import java.io.StringWriter; import java.math.BigInteger; import java.security.InvalidKeyException; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; import java.security.spec.DSAPrivateKeySpec; import java.security.spec.DSAPublicKeySpec; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.RSAPrivateCrtKeySpec; import java.security.spec.RSAPublicKeySpec; import java.security.spec.X509EncodedKeySpec; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.BIT_STRING; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.asn1.SET; import org.mozilla.jss.crypto.PrivateKey; import org.mozilla.jss.crypto.SignatureAlgorithm; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.crypto.TokenSupplierManager; import org.mozilla.jss.pkcs11.PK11PrivKey; import org.mozilla.jss.pkcs11.PK11PubKey; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; import org.mozilla.jss.pkix.primitive.PrivateKeyInfo; import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo; public class KeyFactorySpi1_2 extends java.security.KeyFactorySpi { @Override protected PublicKey engineGeneratePublic(KeySpec keySpec) throws InvalidKeySpecException { if( keySpec instanceof RSAPublicKeySpec ) { RSAPublicKeySpec spec = (RSAPublicKeySpec) keySpec; // Generate a DER RSA public key SEQUENCE seq = new SEQUENCE(); seq.addElement( new INTEGER(spec.getModulus())); seq.addElement( new INTEGER(spec.getPublicExponent())); return PK11PubKey.fromRaw( PrivateKey.RSA, ASN1Util.encode(seq) ); } else if( keySpec instanceof DSAPublicKeySpec ) { // We need to import both the public value and the PQG parameters. // The only way to get all that information in DER is to send // a full SubjectPublicKeyInfo. So we encode all the information // into an SPKI. DSAPublicKeySpec spec = (DSAPublicKeySpec) keySpec; SEQUENCE pqg = new SEQUENCE(); pqg.addElement( new INTEGER(spec.getP()) ); pqg.addElement( new INTEGER(spec.getQ()) ); pqg.addElement( new INTEGER(spec.getG()) ); OBJECT_IDENTIFIER oid = null; try { oid = SignatureAlgorithm.DSASignature.toOID(); } catch(NoSuchAlgorithmException e ) { throw new RuntimeException("No such algorithm: " + e.getMessage(), e); } AlgorithmIdentifier algID = new AlgorithmIdentifier( oid, pqg ); INTEGER publicValue = new INTEGER(spec.getY()); byte[] encodedPublicValue = ASN1Util.encode(publicValue); SubjectPublicKeyInfo spki = new SubjectPublicKeyInfo( algID, new BIT_STRING(encodedPublicValue, 0) ); return PK11PubKey.fromSPKI( ASN1Util.encode(spki) ); // // requires JAVA 1.5 // //} else if( keySpec instanceof ECPublicKeySpec ) { // // We need to import both the public value and the curve. // // The only way to get all that information in DER is to send // // a full SubjectPublicKeyInfo. So we encode all the information // // into an SPKI. // // ECPublicKeySpec spec = (ECPublicKeySpec) keySpec; // AlgorithmParameters algParams = getInstance("ECParameters"); // // algParameters.init(spec.getECParameters()); // OBJECT_IDENTIFIER oid = null; // try { // oid = SignatureAlgorithm.ECSignature.toOID(); // } catch(NoSuchAlgorithmException ex ) { // Assert.notReached("no such algorithm as DSA?"); // } // AlgorithmIdentifier algID = // new AlgorithmIdentifier(oid, ecParams.getParams() ); // INTEGER publicValueX = new INTEGER(spec.getW().getAffineX()); // INTEGER publicValueY = new INTEGER(spec.getW().getAffineY()); // byte[] encodedPublicValue; // encodedPublicValue[0] = EC_UNCOMPRESSED_POINT; // encodedPublicValue += spec.getW().getAffineX().toByteArray(); // encodedPublicValue += spec.getW().getAffineY().toByteArray(); // // byte[] encodedPublicValue = ASN1Util.encode(publicValue); // SubjectPublicKeyInfo spki = new SubjectPublicKeyInfo( // algID, new BIT_STRING(encodedPublicValue, 0) ); // // return PK11PubKey.fromSPKI( ASN1Util.encode(spki) ); // // use the following for EC keys in 1.4.2 } else if( keySpec instanceof X509EncodedKeySpec ) { // // SubjectPublicKeyInfo // X509EncodedKeySpec spec = (X509EncodedKeySpec) keySpec; return PK11PubKey.fromSPKI( spec.getEncoded() ); } throw new InvalidKeySpecException("Unsupported KeySpec type: " + keySpec.getClass().getName()); } /** * We don't support RSAPrivateKeySpec because it doesn't have enough * information. You need to provide an RSAPrivateCrtKeySpec. */ @Override protected java.security.PrivateKey engineGeneratePrivate(KeySpec keySpec) throws InvalidKeySpecException { try { if( keySpec instanceof RSAPrivateCrtKeySpec ) { // // PKCS #1 RSAPrivateKey // RSAPrivateCrtKeySpec spec = (RSAPrivateCrtKeySpec) keySpec; SEQUENCE privKey = new SEQUENCE(); privKey.addElement( new INTEGER(0) ) ; // version privKey.addElement( new INTEGER(spec.getModulus()) ); privKey.addElement( new INTEGER(spec.getPublicExponent()) ); privKey.addElement( new INTEGER(spec.getPrivateExponent()) ); privKey.addElement( new INTEGER(spec.getPrimeP()) ); privKey.addElement( new INTEGER(spec.getPrimeQ()) ); privKey.addElement( new INTEGER(spec.getPrimeExponentP()) ); privKey.addElement( new INTEGER(spec.getPrimeExponentQ()) ); privKey.addElement( new INTEGER(spec.getCrtCoefficient()) ); AlgorithmIdentifier algID = new AlgorithmIdentifier( PrivateKey.RSA.toOID(), null ); OCTET_STRING encodedPrivKey = new OCTET_STRING( ASN1Util.encode(privKey) ); PrivateKeyInfo pki = new PrivateKeyInfo( new INTEGER(0), // version algID, encodedPrivKey, (SET)null // OPTIONAL SET OF Attribute ); return PK11PrivKey.fromPrivateKeyInfo( ASN1Util.encode(pki), TokenSupplierManager.getTokenSupplier().getThreadToken() ); } else if( keySpec instanceof DSAPrivateKeySpec ) { DSAPrivateKeySpec spec = (DSAPrivateKeySpec) keySpec; SEQUENCE pqgParams = new SEQUENCE(); pqgParams.addElement(new INTEGER(spec.getP())); pqgParams.addElement(new INTEGER(spec.getQ())); pqgParams.addElement(new INTEGER(spec.getG())); AlgorithmIdentifier algID = new AlgorithmIdentifier( PrivateKey.DSA.toOID(), pqgParams ); OCTET_STRING privateKey = new OCTET_STRING( ASN1Util.encode(new INTEGER(spec.getX())) ); PrivateKeyInfo pki = new PrivateKeyInfo( new INTEGER(0), // version algID, privateKey, null // OPTIONAL SET OF Attribute ); // Derive the public key from the private key BigInteger y = spec.getG().modPow(spec.getX(), spec.getP()); byte[] yBA = y.toByteArray(); // we need to chop off a leading zero byte if( y.bitLength() % 8 == 0 ) { byte[] newBA = new byte[yBA.length-1]; assert(newBA.length >= 0); System.arraycopy(yBA, 1, newBA, 0, newBA.length); yBA = newBA; } return PK11PrivKey.fromPrivateKeyInfo( ASN1Util.encode(pki), TokenSupplierManager.getTokenSupplier().getThreadToken(), yBA ); } else if( keySpec instanceof PKCS8EncodedKeySpec ) { return PK11PrivKey.fromPrivateKeyInfo( (PKCS8EncodedKeySpec)keySpec, TokenSupplierManager.getTokenSupplier().getThreadToken() ); } throw new InvalidKeySpecException("Unsupported KeySpec type: " + keySpec.getClass().getName()); } catch(TokenException te) { StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); te.printStackTrace(pw); throw new InvalidKeySpecException("TokenException: " + sw.toString()); } } @Override protected T engineGetKeySpec(Key key, Class keySpec) throws InvalidKeySpecException { throw new InvalidKeySpecException( "Exporting raw key data is not supported. Wrap the key instead."); } /** * Translates key by calling getEncoded() to get its encoded form, * then importing the key from its encoding. Two formats are supported: * "X.509", which is decoded with an X509EncodedKeySpec; * and "PKCS#8", which is decoded with a PKCS8EncodedKeySpec. * *

This method is not well standardized: the documentation is very vague * about how the key is supposed to be translated. It is better * to move keys around by wrapping and unwrapping them; or by manually * translating to a KeySpec, then manually translating back to a Key. */ @Override protected Key engineTranslateKey(Key key) throws InvalidKeyException { byte[] encoded = key.getEncoded(); String format = key.getFormat(); try { if( format.equals("SubjectPublicKeyInfo") || format.equalsIgnoreCase("X.509")) { X509EncodedKeySpec spec = new X509EncodedKeySpec(encoded); return engineGeneratePublic(spec); } else if( format.equals("PrivateKeyInfo") || format.equalsIgnoreCase("PKCS#8")) { PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(encoded); return engineGeneratePrivate(spec); } } catch(InvalidKeySpecException e) { throw new InvalidKeyException(e.getMessage()); } throw new InvalidKeyException( "Unsupported encoding format: " + format); } } jss-5.0.0/src/main/java/org/mozilla/jss/provider/java/security/RC2AlgorithmParameters.java000066400000000000000000000041311412550063600315530ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.provider.java.security; import java.io.IOException; import java.security.AlgorithmParametersSpi; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.InvalidParameterSpecException; import javax.crypto.spec.RC2ParameterSpec; /** * This class is only intended to be used to implement * CipherSpi.getAlgorithmParameters(). */ public class RC2AlgorithmParameters extends AlgorithmParametersSpi { private RC2ParameterSpec RC2ParamSpec; @Override public void engineInit(AlgorithmParameterSpec paramSpec) { RC2ParamSpec = (RC2ParameterSpec) paramSpec; } @Override public T engineGetParameterSpec(Class clazz) throws InvalidParameterSpecException { if( clazz != null && !clazz.isInstance(RC2ParamSpec) ) { Class paramSpecClass = RC2ParamSpec.getClass(); throw new InvalidParameterSpecException( "RC2 getParameterSpec has class " + paramSpecClass.getName()); } return clazz.cast(RC2ParamSpec); } @Override public void engineInit(byte[] params) throws IOException { throw new IOException("engineInit(byte[]) not supported"); } @Override public void engineInit(byte[] params, String format) throws IOException { throw new IOException("engineInit(byte[],String) not supported"); } @Override public byte[] engineGetEncoded() throws IOException { throw new IOException("encoding RC2AlgorithmParameters not supported"); } @Override public byte[] engineGetEncoded(String format) throws IOException { throw new IOException("encoding RC2AlgorithmParameters not supported"); } @Override public String engineToString() { String str = new String("Mozilla-JSS RC2AlgorithmParameters " + getClass().getName()); return str; } } jss-5.0.0/src/main/java/org/mozilla/jss/provider/java/security/RSAPSSAlgorithmParameters.java000066400000000000000000000213201412550063600321770ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.provider.java.security; import java.security.*; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.InvalidParameterSpecException; import java.security.spec.PSSParameterSpec; import java.security.spec.MGF1ParameterSpec; import java.io.IOException; import org.mozilla.jss.util.Assert; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.x509.AlgorithmId; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; /** * A RSAPSSAlgorithmParameter implements the trandcoding between a * PSSAlgorithmSpec instance and the DER-encoded form. * * RSASSA-PSS-params ::= SEQUENCE { * hashAlgorithm [0] OAEP-PSSDigestAlgorithms DEFAULT sha1, * maskGenAlgorithm [1] PKCS1MGFAlgorithms DEFAULT mgf1SHA1, * saltLength [2] INTEGER DEFAULT 20, * trailerField [3] INTEGER DEFAULT 1 * } * * where * * OAEP-PSSDigestAlgorithms ALGORITHM-IDENTIFIER ::= { * { OID id-sha1 PARAMETERS NULL }| * { OID id-sha224 PARAMETERS NULL }| * { OID id-sha256 PARAMETERS NULL }| * { OID id-sha384 PARAMETERS NULL }| * { OID id-sha512 PARAMETERS NULL }, * ... -- Allows for future expansion -- * } * * PKCS1MGFAlgorithms ALGORITHM-IDENTIFIER ::= { * { OID id-mgf1 PARAMETERS OAEP-PSSDigestAlgorithms }, * ... -- Allows for future expansion -- * } */ public class RSAPSSAlgorithmParameters extends AlgorithmParametersSpi { public final static AlgorithmId defaultHashAlg = new AlgorithmId(AlgorithmId.SHA_oid); public final static AlgorithmId defaultMaskGenFunc = new AlgorithmId(AlgorithmId.MGF1_oid); public final static BigInt defaultSaltLen = new BigInt(20); public final static BigInt defaultTrailerField = new BigInt(1); private PSSParameterSpec spec = PSSParameterSpec.DEFAULT; private AlgorithmId hashAlg = defaultHashAlg; private AlgorithmId maskGenFunc = defaultMaskGenFunc; private BigInt saltLen = defaultSaltLen; private BigInt trailerField = defaultTrailerField; public RSAPSSAlgorithmParameters() {} @Override protected void engineInit(AlgorithmParameterSpec paramSpec) throws InvalidParameterSpecException { spec = (PSSParameterSpec) paramSpec; populateFromSpec(); } @Override protected T engineGetParameterSpec(Class paramSpec) throws InvalidParameterSpecException { if (paramSpec.isAssignableFrom(PSSParameterSpec.class)) { return paramSpec.cast(spec); } throw new InvalidParameterSpecException("Unknown parameter spec passed to PSS parameters object: " + paramSpec.getName()); } @Override protected void engineInit(byte[] params) throws IOException { decode(new DerInputStream(params), params); } @Override protected void engineInit(byte[] params, String format) throws IOException { // Assume Der for now. Assert.notReached("engineInit(byte[],String) not supported"); throw new IOException("engineInit(byte[],String) not supported"); } @Override protected byte[] engineGetEncoded() throws IOException { DerOutputStream out = new DerOutputStream(); encode(out); return out.toByteArray(); } @Override protected byte[] engineGetEncoded(String format) throws IOException { //Assume Der for now. Assert.notReached("engineGetEncoded(String format)) not supported"); throw new IOException("engineGetEncoded(String format)) not supported"); } @Override protected String engineToString() { String str = new String("Mozilla-JSS PSSAlgorithmParameters " + getClass().getName() + " HashAlg: " + spec.getDigestAlgorithm() + " MaskGenAlg: " + spec.getMGFAlgorithm() ); return str; } private void decode(DerInputStream in , byte[] encoded) throws IOException { if (in == null) { throw new IOException("Invalid input: got null DerInputStream"); } // Sequence has 3 members, trailer field ignored DerValue seq[] = in.getSequence(3); if (seq.length < 3 || seq.length > 4) { throw new IOException("Invalid data! Expected a sequence with either 3 or 4 members; got " + seq.length); } if (seq[0].isContextSpecific((byte)0)) { seq[0] = seq[0].data.getDerValue(); } else { throw new IOException("Invalid encoded data! Expecting OAEP-PSSDigestAlgorithms (hashAlgorithm)."); } AlgorithmId algid = AlgorithmId.parse(seq[0]); String specAlgName = getSpecAlgName(algid.getName()); String specMGF1Name = ""; // Now the MFG1 parameter hash fun is the same as the main hash func. MGF1ParameterSpec specMFG1ParamSpec = new MGF1ParameterSpec(specAlgName); if (seq[1].isContextSpecific((byte)1)) { seq[1] = seq[1].data.getDerValue(); } else { throw new IOException("Invalid encoded data! Expecting OAEP-PSSDigestAlgorithms (maskGenAlgorithm)."); } DerInputStream mgf1Str = new DerInputStream(seq[1].toByteArray()); DerValue[] seqMgf1 = mgf1Str.getSequence(2); ObjectIdentifier mgf1OID = seqMgf1[0].getOID(); if (!mgf1OID.equals(AlgorithmId.MGF1_oid)) { throw new IOException("Invalid encoded data: expected MGF1 OID but got: " + mgf1OID.toString()); } else { specMGF1Name = "MGF1"; } if (seq[2].isContextSpecific((byte)2)) { seq[2] = seq[2].data.getDerValue(); } else { throw new IOException("Invalid encoded data! Expected INTEGER (saltLength)."); } BigInt sLength = seq[2].getInteger(); this.spec = new PSSParameterSpec(specAlgName, specMGF1Name, specMFG1ParamSpec, sLength.toInt(), 1 /* always default trailer */); populateFromSpec(); } private void encode(DerOutputStream out) throws IOException { try ( DerOutputStream tmp = new DerOutputStream(); DerOutputStream mgf = new DerOutputStream(); DerOutputStream seq1 = new DerOutputStream(); DerOutputStream intStream = new DerOutputStream(); ) { // Hash algorithm hashAlg.derEncodeWithContext(tmp,0); // Mask Gen Function Sequence mgf.putOID(maskGenFunc.getOID()); // MGF hash alg is the same as the hash Alg at this point. hashAlg.encode(mgf); seq1.write(DerValue.tag_Sequence,mgf); tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 1), seq1); // Salt Length intStream.putInteger(saltLen); tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 2), intStream); // Ignore trailer field, it never changes over all sequence tags out.write(DerValue.tag_Sequence, tmp); byte[] data = out.toByteArray(); } } private void populateFromSpec() { if (spec == null || hashAlg == null) { return; } String hashAlgName = spec.getDigestAlgorithm(); String maskGenName = spec.getMGFAlgorithm(); int saltLen = spec.getSaltLength(); this.saltLen = new BigInt(saltLen); int trailer = spec.getTrailerField(); // Create the hash alg and mask gen func objects if (hashAlgName.equals("SHA-256")) { hashAlg = new AlgorithmId(AlgorithmId.SHA256_oid); } else if(hashAlgName.equals("SHA-512")) { hashAlg = new AlgorithmId(AlgorithmId.SHA512_oid); } else if(hashAlgName.equals("SHA-384")) { hashAlg = new AlgorithmId(AlgorithmId.SHA384_oid); } else { // Default to SHA-1 per above ASN.1 encoding. hashAlg = new AlgorithmId(AlgorithmId.SHA_oid); } } private String getSpecAlgName(String algName) { if ("SHA256".equals(algName)) { return "SHA-256"; } else if("SHA384".equals(algName)) { return "SHA-384"; } else if("SHA512".equals(algName)) { return "SHA-512"; } else { // Default to SHA-1 per above ASN.1 encoding. return "SHA-1"; } } } jss-5.0.0/src/main/java/org/mozilla/jss/provider/javax/000077500000000000000000000000001412550063600227515ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/provider/javax/crypto/000077500000000000000000000000001412550063600242715ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/provider/javax/crypto/JSSCipherSpi.java000066400000000000000000000466571412550063600274240ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.provider.javax.crypto; import java.security.AlgorithmParameters; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.PublicKey; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.InvalidParameterSpecException; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.ShortBufferException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.RC2ParameterSpec; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.BIT_STRING; import org.mozilla.jss.asn1.InvalidBERException; import org.mozilla.jss.crypto.Algorithm; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.EncryptionAlgorithm; import org.mozilla.jss.crypto.KeyWrapAlgorithm; import org.mozilla.jss.crypto.SecretKeyFacade; import org.mozilla.jss.crypto.SymmetricKey; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.crypto.TokenRuntimeException; import org.mozilla.jss.crypto.TokenSupplierManager; import org.mozilla.jss.pkcs11.PK11PrivKey; import org.mozilla.jss.pkcs11.PK11PubKey; import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo; public class JSSCipherSpi extends javax.crypto.CipherSpi { private String algFamily=null; private String algMode=null; private String algPadding=null; CryptoToken token = null; private org.mozilla.jss.crypto.Cipher cipher=null; private EncryptionAlgorithm encAlg = null; private org.mozilla.jss.crypto.KeyWrapper wrapper=null; private KeyWrapAlgorithm wrapAlg = null; private AlgorithmParameterSpec params = null; private int blockSize; //keyStrength is used for RC2ParameterSpec and EncryptionAlgorithm.lookup private int keyStrength; protected JSSCipherSpi(String algFamily) { this.algFamily = algFamily; token = TokenSupplierManager.getTokenSupplier().getThreadToken(); } @Override public void engineSetMode(String mode) { this.algMode = mode; } @Override public void engineSetPadding(String padding) { this.algPadding = padding; } static private SecretKey importKey(Key key) throws InvalidKeyException { if (key instanceof SecretKey) { SecretKey sKey = (SecretKey) key; SecretKeyFactory fact = null; try { fact = SecretKeyFactory.getInstance(sKey.getAlgorithm(), "Mozilla-JSS"); } catch (NoSuchAlgorithmException e) { throw new InvalidKeyException( "Unable to translate key with Algorithm" + key.getAlgorithm()); } catch (NoSuchProviderException ex) { throw new InvalidKeyException( "Unable to find provider, this should not happen"); } return fact.translateKey(sKey); }else { throw new InvalidKeyException("Invalid key type: " + key.getClass().getName()); } } @Override public void engineInit(int opmode, Key key, AlgorithmParameterSpec givenParams, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { try { // throw away any previous state cipher = null; wrapper = null; params = givenParams; if( algFamily==null ) { throw new InvalidAlgorithmParameterException( "incorrectly specified algorithm"); } if( opmode != Cipher.ENCRYPT_MODE && opmode != Cipher.DECRYPT_MODE && opmode != Cipher.WRAP_MODE && opmode != Cipher.UNWRAP_MODE ) { throw new InvalidKeyException("Invalid opmode"); } StringBuffer buf = new StringBuffer(); buf.append(algFamily); if( algMode != null ) { buf.append('/'); buf.append(algMode); } if( algPadding != null ) { buf.append('/'); buf.append(algPadding); } if( opmode == Cipher.ENCRYPT_MODE || opmode == Cipher.DECRYPT_MODE ) { if( ! (key instanceof SecretKeyFacade) ) { key = importKey(key); } SymmetricKey symkey = ((SecretKeyFacade)key).key; // lookup the encryption algorithm keyStrength = symkey.getStrength(); encAlg = EncryptionAlgorithm.lookup(algFamily, algMode, algPadding, keyStrength); blockSize = encAlg.getBlockSize(); if( !token.doesAlgorithm(encAlg) ) { throw new NoSuchAlgorithmException( encAlg.toString() + " is not supported by this token " + token.getName()); } cipher = token.getCipherContext(encAlg); if( opmode == Cipher.ENCRYPT_MODE ) { if( params == noAlgParams ) { // we're supposed to generate some params params = generateAlgParams(encAlg, blockSize); } cipher.initEncrypt(symkey, params); } else if( opmode == Cipher.DECRYPT_MODE ) { if( params == noAlgParams) { params = null; } cipher.initDecrypt(symkey, params); } } else { assert( opmode==Cipher.WRAP_MODE || opmode==Cipher.UNWRAP_MODE); wrapAlg = KeyWrapAlgorithm.fromString(buf.toString()); blockSize = wrapAlg.getBlockSize(); wrapper = token.getKeyWrapper(wrapAlg); // generate params if necessary if( params == noAlgParams ) { if( opmode == Cipher.WRAP_MODE ) { params = generateAlgParams(wrapAlg, blockSize); } else { assert(opmode == Cipher.UNWRAP_MODE); params = null; } } if( key instanceof org.mozilla.jss.crypto.PrivateKey ) { if( opmode != Cipher.UNWRAP_MODE ) { throw new InvalidKeyException( "Private key can only be used for unwrapping"); } wrapper.initUnwrap( (org.mozilla.jss.crypto.PrivateKey) key, params ); } else if( key instanceof PublicKey ) { if( opmode != Cipher.WRAP_MODE ) { throw new InvalidKeyException( "Public key can only be used for wrapping"); } wrapper.initWrap((PublicKey) key, params); } else if( key instanceof org.mozilla.jss.crypto.SecretKeyFacade) { org.mozilla.jss.crypto.SecretKeyFacade sk = (org.mozilla.jss.crypto.SecretKeyFacade) key; if( opmode == Cipher.WRAP_MODE ) { wrapper.initWrap( sk.key, params ); } else { assert(opmode==Cipher.UNWRAP_MODE); wrapper.initUnwrap( sk.key, params ); } } else { throw new InvalidKeyException("Invalid key type: " + key.getClass().getName()); } } } catch (NoSuchAlgorithmException e) { throw new InvalidAlgorithmParameterException(e.getMessage()); } catch(TokenException te) { throw new TokenRuntimeException(te.getMessage()); } } @Override public void engineInit(int opmode, Key key, AlgorithmParameters givenParams, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { try { AlgorithmParameterSpec gp = null; if (algFamily.compareToIgnoreCase("RC2") == 0) { gp = givenParams.getParameterSpec( javax.crypto.spec.RC2ParameterSpec.class ); } else if (algMode.compareToIgnoreCase("CBC") == 0) { gp = givenParams.getParameterSpec( javax.crypto.spec.IvParameterSpec.class ); } if (gp != null) { engineInit(opmode, key, gp, random); } else { throw new InvalidAlgorithmParameterException("Unknown Parameter Spec"); } } catch(Exception e) { throw new InvalidAlgorithmParameterException(e.getMessage()); } } @Override public void engineInit(int opmode, Key key, SecureRandom random) throws InvalidKeyException { try { engineInit(opmode, key, noAlgParams, random); } catch(InvalidAlgorithmParameterException e) { throw new InvalidKeyException(e.getMessage()); } } private AlgorithmParameterSpec generateAlgParams(Algorithm alg, int blockSize) throws InvalidKeyException { Class [] paramClasses = alg.getParameterClasses(); AlgorithmParameterSpec algParSpec = null; if( paramClasses == null ) { // no parameters are needed return null; } // generate an IV byte[] iv = new byte[blockSize]; try { SecureRandom random = SecureRandom.getInstance("pkcs11prng", "Mozilla-JSS"); random.nextBytes(iv); } catch (Exception e) { throw new RuntimeException(e); } for (int i = 0; i < paramClasses.length; i ++) { if( paramClasses[i].equals( javax.crypto.spec.IvParameterSpec.class ) ) { algParSpec = new javax.crypto.spec.IvParameterSpec(iv); break; } else if ( paramClasses[i].equals( RC2ParameterSpec.class ) ) { algParSpec = new RC2ParameterSpec(keyStrength, iv); break; } } return algParSpec; } private static class NoAlgParams implements AlgorithmParameterSpec { } private static final NoAlgParams noAlgParams = new NoAlgParams(); @Override public int engineGetBlockSize() { return blockSize; } @Override public byte[] engineGetIV() { if( params == null ) { return null; } if( params instanceof IvParameterSpec) { return ((IvParameterSpec)params).getIV(); } else if( params instanceof RC2ParameterSpec ) { return ((RC2ParameterSpec)params).getIV(); } else { return null; } } @Override public AlgorithmParameters engineGetParameters() { AlgorithmParameters algParams = null; try { if(( params instanceof IvParameterSpec ) || ( params instanceof RC2ParameterSpec )) { algParams = AlgorithmParameters.getInstance(algFamily); algParams.init(params); } } catch(NoSuchAlgorithmException e) { throw new RuntimeException("Unable to get parameters: " + e.getMessage(), e); } catch(InvalidParameterSpecException e) { throw new RuntimeException("Unable to get parameters: " + e.getMessage(), e); } return algParams; } @Override public int engineGetOutputSize(int inputLen) { int total = (blockSize-1) + inputLen; return ((total / blockSize) + 1) * blockSize; } @Override public byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) { if(cipher == null) { // Cipher is supposed to catch an illegal state, so we should never // get here throw new IllegalStateException(); } try { return cipher.update(input, inputOffset, inputLen); } catch(TokenException te) { throw new TokenRuntimeException(te.getMessage()); } } @Override public int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws ShortBufferException { byte[] bytes = engineUpdate(input, inputOffset, inputLen); if( bytes.length > output.length-outputOffset ) { throw new ShortBufferException(bytes.length + " needed, " + (output.length-outputOffset) + " supplied"); } System.arraycopy(bytes, 0, output, outputOffset, bytes.length); return bytes.length; } @Override public byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen) throws IllegalBlockSizeException, BadPaddingException { if( cipher == null ) { // Cipher is supposed to catch an illegal state, so we should never // get here throw new IllegalStateException(); } try { if( input == null || inputLen == 0) { return cipher.doFinal(); } else { return cipher.doFinal(input, inputOffset, inputLen); } } catch(IllegalStateException ise) { throw ise; } catch(org.mozilla.jss.crypto.IllegalBlockSizeException ibse) { throw new IllegalBlockSizeException(ibse.getMessage()); } catch(TokenException te) { throw new TokenRuntimeException(te.getMessage()); } } @Override public int engineDoFinal(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset) throws ShortBufferException, IllegalBlockSizeException, BadPaddingException { byte[] bytes = engineDoFinal(input, inputOffset, inputLen); if( bytes.length > output.length-outputOffset ) { throw new ShortBufferException(bytes.length + " needed, " + (output.length-outputOffset) + " supplied"); } System.arraycopy(bytes, 0, output, outputOffset, bytes.length); return bytes.length; } @Override public byte[] engineWrap(Key key) throws IllegalBlockSizeException, InvalidKeyException { if( wrapper == null ) { throw new IllegalStateException(); } try { if( key instanceof org.mozilla.jss.crypto.PrivateKey ) { return wrapper.wrap( (org.mozilla.jss.crypto.PrivateKey) key); } else if( key instanceof org.mozilla.jss.crypto.SecretKeyFacade) { return wrapper.wrap( ((org.mozilla.jss.crypto.SecretKeyFacade)key).key ); } else { throw new InvalidKeyException("Unsupported key type: " + key.getClass().getName()); } } catch(IllegalStateException ise) { throw ise; } catch(TokenException te) { throw new TokenRuntimeException(te.getMessage()); } } @Override public Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, int wrappedKeyType) throws InvalidKeyException, NoSuchAlgorithmException { if( wrapper == null ) { throw new IllegalStateException(); } try { switch(wrappedKeyType) { case Cipher.SECRET_KEY: return engineUnwrapSecret(wrappedKey, wrappedKeyAlgorithm); case Cipher.PRIVATE_KEY: return engineUnwrapPrivate(wrappedKey, wrappedKeyAlgorithm); case Cipher.PUBLIC_KEY: throw new UnsupportedOperationException( "Unable to unwrap public keys"); default: throw new NoSuchAlgorithmException( "Invalid key type: " + wrappedKeyType); } } catch(IllegalStateException ise) { throw ise; } } private Key engineUnwrapSecret(byte[] wrappedKey, String wrappedKeyAlg) throws InvalidKeyException, NoSuchAlgorithmException { try { int idx = wrappedKeyAlg.indexOf('/'); if( idx != -1 ) { wrappedKeyAlg = wrappedKeyAlg.substring(0, idx); } SymmetricKey.Type wrappedKeyType = SymmetricKey.Type.fromName(wrappedKeyAlg); // Specify 0 for key length. This will use the default key length. // Won't work for algorithms without a default, like RC4, unless a // padded algorithm is used. SymmetricKey key = wrapper.unwrapSymmetric(wrappedKey, wrappedKeyType, 0); return new SecretKeyFacade(key); } catch(StringIndexOutOfBoundsException e) { throw new NoSuchAlgorithmException("Unknown algorithm: " + wrappedKeyAlg); } catch(TokenException te ) { throw new TokenRuntimeException(te.getMessage()); } catch(InvalidAlgorithmParameterException iape ) { throw new NoSuchAlgorithmException("Invalid algorithm parameters" + iape.getMessage()); } } private Key engineUnwrapPrivate(byte[] wrappedKey, String wrappedKeyAlg) throws InvalidKeyException, NoSuchAlgorithmException { throw new NoSuchAlgorithmException( "Unwrapping private keys via the JCA interface is not supported: "+ "http://bugzilla.mozilla.org/show_bug.cgi?id=135328"); } @Override public int engineGetKeySize(Key key) throws InvalidKeyException { if( key instanceof PK11PrivKey ) { return ((PK11PrivKey)key).getStrength(); } else if( key instanceof PK11PubKey ) { try { byte[] encoded = ((PK11PubKey)key).getEncoded(); SubjectPublicKeyInfo.Template spkiTemp = new SubjectPublicKeyInfo.Template(); SubjectPublicKeyInfo spki = (SubjectPublicKeyInfo) ASN1Util.decode(spkiTemp, encoded); BIT_STRING pk = spki.getSubjectPublicKey(); return pk.getBits().length - pk.getPadCount(); } catch(InvalidBERException e) { throw new InvalidKeyException("Exception while decoding " + "public key: " + e.getMessage()); } } else if( key instanceof SecretKeyFacade ) { SymmetricKey symkey = ((SecretKeyFacade)key).key; return symkey.getLength(); } else { key = importKey(key); SymmetricKey symkey = ((SecretKeyFacade)key).key; return symkey.getLength(); } } static public class DES extends JSSCipherSpi { public DES() { super("DES"); } } static public class DESede extends JSSCipherSpi { public DESede() { super("DESede"); } } static public class AES extends JSSCipherSpi { public AES() { super("AES"); } } static public class RC4 extends JSSCipherSpi { public RC4() { super("RC4"); } } static public class RSA extends JSSCipherSpi { public RSA() { super("RSA"); } } static public class RC2 extends JSSCipherSpi { public RC2() { super("RC2"); } } } jss-5.0.0/src/main/java/org/mozilla/jss/provider/javax/crypto/JSSKeyGeneratorSpi.java000066400000000000000000000124011412550063600305650ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.provider.javax.crypto; import java.io.CharConversionException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidParameterException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.SecretKey; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.KeyGenAlgorithm; import org.mozilla.jss.crypto.KeyGenerator; import org.mozilla.jss.crypto.SecretKeyFacade; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.crypto.TokenRuntimeException; import org.mozilla.jss.crypto.TokenSupplierManager; public class JSSKeyGeneratorSpi extends javax.crypto.KeyGeneratorSpi { private KeyGenerator keyGenerator= null; protected JSSKeyGeneratorSpi(KeyGenAlgorithm alg) { try { CryptoToken token = TokenSupplierManager.getTokenSupplier().getThreadToken(); keyGenerator = token.getKeyGenerator(alg); } catch( TokenException te) { throw new TokenRuntimeException(te.getMessage()); } catch(NoSuchAlgorithmException nsae) { throw new TokenRuntimeException(nsae.getMessage()); } } @Override protected void engineInit(int keysize, SecureRandom random) throws InvalidParameterException { try { keyGenerator.initialize(keysize); } catch(InvalidAlgorithmParameterException e) { throw new InvalidParameterException(e.getMessage()); } } @Override protected void engineInit( SecureRandom random) throws InvalidParameterException { // no-op. KeyGenerator.initialize isn't called if there // are no arguments. } @Override protected void engineInit(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException { keyGenerator.initialize(params); } @Override protected SecretKey engineGenerateKey() { try { return new SecretKeyFacade( keyGenerator.generate() ); } catch(IllegalStateException ise) { throw new TokenRuntimeException( "IllegalStateException: " + ise.getMessage()); } catch(TokenException te) { throw new TokenRuntimeException( te.getMessage()); } catch(CharConversionException cce) { throw new TokenRuntimeException( "CharConversionException: " + cce.getMessage()); } } public static class DES extends JSSKeyGeneratorSpi { public DES() { super(KeyGenAlgorithm.DES); } } public static class DESede extends JSSKeyGeneratorSpi { public DESede() { super(KeyGenAlgorithm.DESede); } } public static class AES extends JSSKeyGeneratorSpi { public AES() { super(KeyGenAlgorithm.AES); } } public static class RC4 extends JSSKeyGeneratorSpi { public RC4() { super(KeyGenAlgorithm.RC4); } } public static class RC2 extends JSSKeyGeneratorSpi { public RC2() { super(KeyGenAlgorithm.RC2); } } public static class HmacSHA1 extends JSSKeyGeneratorSpi { public HmacSHA1() { super(KeyGenAlgorithm.SHA1_HMAC); } } public static class PBAHmacSHA1 extends JSSKeyGeneratorSpi { public PBAHmacSHA1() { super(KeyGenAlgorithm.PBA_SHA1_HMAC); } } public static class HmacSHA256 extends JSSKeyGeneratorSpi { public HmacSHA256() { super(KeyGenAlgorithm.SHA256_HMAC); } } public static class HmacSHA384 extends JSSKeyGeneratorSpi { public HmacSHA384() { super(KeyGenAlgorithm.SHA384_HMAC); } } public static class HmacSHA512 extends JSSKeyGeneratorSpi { public HmacSHA512() { super(KeyGenAlgorithm.SHA512_HMAC); } } public static class KbkdfCounter extends JSSKeyGeneratorSpi { public KbkdfCounter() { super(KeyGenAlgorithm.SP800_108_COUNTER_KDF); } } public static class KbkdfFeedback extends JSSKeyGeneratorSpi { public KbkdfFeedback() { super(KeyGenAlgorithm.SP800_108_FEEDBACK_KDF); } } public static class KbkdfDoublePipeline extends JSSKeyGeneratorSpi { public KbkdfDoublePipeline() { super(KeyGenAlgorithm.SP800_108_DOUBLE_PIPELINE_KDF); } } public static class KbkdfCounterData extends JSSKeyGeneratorSpi { public KbkdfCounterData() { super(KeyGenAlgorithm.NSS_SP800_108_COUNTER_KDF_DERIVE_DATA); } } public static class KbkdfFeedbackData extends JSSKeyGeneratorSpi { public KbkdfFeedbackData() { super(KeyGenAlgorithm.NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA); } } public static class KbkdfDoublePipelineData extends JSSKeyGeneratorSpi { public KbkdfDoublePipelineData() { super(KeyGenAlgorithm.NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA); } } } jss-5.0.0/src/main/java/org/mozilla/jss/provider/javax/crypto/JSSKeyManager.java000066400000000000000000000004651412550063600275440ustar00rootroot00000000000000package org.mozilla.jss.provider.javax.crypto; import javax.net.ssl.X509KeyManager; /** * All JSSKeyManagers are X509KeyManagers that return PK11Cert * instances. */ public interface JSSKeyManager extends X509KeyManager { public org.mozilla.jss.crypto.X509Certificate getCertificate(String alias); } jss-5.0.0/src/main/java/org/mozilla/jss/provider/javax/crypto/JSSKeyManagerFactory.java000066400000000000000000000045141412550063600310730ustar00rootroot00000000000000package org.mozilla.jss.provider.javax.crypto; import java.security.*; import javax.net.ssl.*; import org.mozilla.jss.*; import org.mozilla.jss.util.*; public class JSSKeyManagerFactory extends KeyManagerFactorySpi { private KeyStore internalStorage; char[] password; @Override protected void engineInit(KeyStore ks, char[] password) throws KeyStoreException { if (password != null) { engineInitCryptoManager(password); // We need to keep this password around and give it to the // JSSKeyManager instance; the KeyStore API requires a password // to open private keys, though JSS might not necessarily use // that. this.password = password; } if (ks != null) { engineInitKeyStore(ks); } } protected void engineInitCryptoManager(char[] password) throws KeyStoreException { try { // At most, we can update the password callback if one doesn't exist. CryptoManager cm = CryptoManager.getInstance(); if (cm.getPasswordCallback() == null && password != null) { PasswordCallback callback = new Password(password); cm.setPasswordCallback(callback); } } catch (Exception e) { throw new KeyStoreException(e.getMessage(), e); } } protected void engineInitKeyStore(KeyStore ks) throws KeyStoreException { try { if (!ks.getProvider().getName().equals("Mozilla-JSS")) { String msg = "Unable to initialize JSSKeyManagerFactory "; msg += "with key store from non-JSS provider."; throw new KeyStoreException(msg); } internalStorage = ks; } catch (Exception e) { throw new KeyStoreException(e.getMessage(), e); } } @Override protected void engineInit(ManagerFactoryParameters spec) { // There is nothing we can do here, so exit without initializing // anything. In the future, we can provide a method to return // multiple token-specific KeyManagers. } @Override protected KeyManager[] engineGetKeyManagers() { KeyManager[] kms = new KeyManager[1]; kms[0] = new JSSTokenKeyManager(internalStorage, password); return kms; } } jss-5.0.0/src/main/java/org/mozilla/jss/provider/javax/crypto/JSSMacSpi.java000066400000000000000000000136661412550063600267040ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.provider.javax.crypto; import java.security.DigestException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.Key; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.InvalidKeySpecException; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.SecretKeySpec; import org.mozilla.jss.crypto.CMACAlgorithm; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.DigestAlgorithm; import org.mozilla.jss.crypto.HMACAlgorithm; import org.mozilla.jss.crypto.JSSMessageDigest; import org.mozilla.jss.crypto.SecretKeyFacade; import org.mozilla.jss.crypto.SymmetricKey; import org.mozilla.jss.crypto.TokenRuntimeException; import org.mozilla.jss.crypto.TokenSupplierManager; public class JSSMacSpi extends javax.crypto.MacSpi { private JSSMessageDigest digest=null; private DigestAlgorithm alg; private String keyName; protected JSSMacSpi(DigestAlgorithm alg, String keyName) { try { this.alg = alg; this.keyName = keyName; CryptoToken token = TokenSupplierManager.getTokenSupplier().getThreadToken(); digest = token.getDigestContext(alg); } catch( DigestException de) { throw new TokenRuntimeException(de.getMessage()); } catch(NoSuchAlgorithmException nsae) { throw new TokenRuntimeException(nsae.getMessage()); } } @Override public int engineGetMacLength() { return alg.getOutputSize(); } @Override public void engineInit(Key key, AlgorithmParameterSpec params) throws InvalidKeyException, InvalidAlgorithmParameterException { try { SymmetricKey real_key = null; if (key instanceof SecretKeyFacade) { SecretKeyFacade facade = (SecretKeyFacade)key; real_key = facade.key; } else if (key instanceof SymmetricKey) { real_key = (SymmetricKey)key; } else if (key.getEncoded() != null) { SecretKeyFactory factory = SecretKeyFactory.getInstance(keyName, "Mozilla-JSS"); SecretKeySpec spec = new SecretKeySpec(key.getEncoded(), keyName); Key manufactured = factory.generateSecret(spec); if (manufactured instanceof SecretKeyFacade) { SecretKeyFacade facade = (SecretKeyFacade)manufactured; real_key = facade.key; } else if (manufactured instanceof SymmetricKey) { real_key = (SymmetricKey)manufactured; } else { String msg = "Internal error while converting key: "; msg += "SecretKeyFactory gave unrecognized manufactured "; msg += "key type: " + manufactured.getClass().getName(); throw new InvalidKeyException(msg); } } else { String msg = "Must use a key created by JSS; got "; msg += key.getClass().getName() + ". "; msg += "Try exporting the key data and importing it via "; msg += "SecretKeyFactory or use an exportable key type "; msg += "so JSS can do this automatically."; throw new InvalidKeyException(msg); } digest.initHMAC(real_key); } catch (DigestException de) { throw new InvalidKeyException("DigestException: " + de.getMessage(), de); } catch (NoSuchAlgorithmException nsae) { throw new InvalidKeyException("NoSuchAlgorithmException when importing key to JSS: " + nsae.getMessage(), nsae); } catch (NoSuchProviderException nspe) { throw new InvalidKeyException("NoSuchProviderException when importing key to JSS: " + nspe.getMessage(), nspe); } catch (InvalidKeySpecException ikse) { throw new InvalidKeyException("InvalidKeySpecException when importing key to JSS: " + ikse.getMessage(), ikse); } } @Override public void engineUpdate(byte input) { try { digest.update(input); } catch(DigestException de) { throw new TokenRuntimeException("DigestException: " + de.getMessage()); } } @Override public void engineUpdate(byte[] input, int offset, int len) { try { digest.update(input, offset, len); } catch(DigestException de) { throw new TokenRuntimeException("DigestException: " + de.getMessage()); } } @Override public byte[] engineDoFinal() { try { return digest.digest(); } catch(DigestException de) { throw new TokenRuntimeException("DigestException: " + de.getMessage()); } } @Override public void engineReset() { try { digest.reset(); } catch(DigestException de) { throw new TokenRuntimeException("DigestException: " + de.getMessage()); } } @Override public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } public static class HmacSHA1 extends JSSMacSpi { public HmacSHA1() { super(HMACAlgorithm.SHA1, "HmacSHA1"); } } public static class HmacSHA256 extends JSSMacSpi { public HmacSHA256() { super(HMACAlgorithm.SHA256, "HmacSHA256"); } } public static class HmacSHA384 extends JSSMacSpi { public HmacSHA384() { super(HMACAlgorithm.SHA384, "HmacSHA384"); } } public static class HmacSHA512 extends JSSMacSpi { public HmacSHA512() { super(HMACAlgorithm.SHA512, "HmacSHA512"); } } public static class CmacAES extends JSSMacSpi { public CmacAES() { super(CMACAlgorithm.AES, "AES"); } } } jss-5.0.0/src/main/java/org/mozilla/jss/provider/javax/crypto/JSSNativeTrustManager.java000066400000000000000000000027711412550063600313060ustar00rootroot00000000000000package org.mozilla.jss.provider.javax.crypto; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.X509TrustManager; /** * JSSNativeTrustManager is a JSSEngine TrustManager utilizing existing native * certificate checking functionality of NSS and JSS, compatible with the old * SSLSocket checks. * * Note: This class isn't compatible with external (non-JSS) SSLEngines. * * The only configuration possible is in CryptoManager's OCSP Policy, which * this obeys. No other configuration is possible. This is more performant * than other TrustManagers, because it saves a JNI call and handles the NSS * callback directly. */ public class JSSNativeTrustManager implements X509TrustManager { private String error_msg = getClass().getName() + " should not be used " + "directly! Please use it with JSSEngine. Note " + "that this TrustManager must be the only one " + "passed to JSSEngine."; @Override public void checkClientTrusted(X509Certificate[] certChain, String authType) throws CertificateException { throw new RuntimeException(error_msg); } @Override public void checkServerTrusted(X509Certificate[] certChain, String authType) throws CertificateException { throw new RuntimeException(error_msg); } @Override public X509Certificate[] getAcceptedIssuers() { throw new RuntimeException(error_msg); } } jss-5.0.0/src/main/java/org/mozilla/jss/provider/javax/crypto/JSSSecretKeyFactorySpi.java000066400000000000000000000416051412550063600314240ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.provider.javax.crypto; import java.io.CharConversionException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.SecretKeyFactorySpi; import javax.crypto.spec.DESKeySpec; import javax.crypto.spec.DESedeKeySpec; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.SecretKeySpec; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.EncryptionAlgorithm; import org.mozilla.jss.crypto.KeyGenAlgorithm; import org.mozilla.jss.crypto.KeyWrapAlgorithm; import org.mozilla.jss.crypto.KeyWrapper; import org.mozilla.jss.crypto.PBEAlgorithm; import org.mozilla.jss.crypto.PBEKeyGenParams; import org.mozilla.jss.crypto.SecretKeyFacade; import org.mozilla.jss.crypto.SymmetricKey; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.crypto.TokenRuntimeException; import org.mozilla.jss.crypto.TokenSupplierManager; import org.mozilla.jss.util.Password; public class JSSSecretKeyFactorySpi extends SecretKeyFactorySpi { private KeyGenAlgorithm alg = null; private CryptoToken token = null; protected JSSSecretKeyFactorySpi(KeyGenAlgorithm alg) { this.alg = alg; token = TokenSupplierManager.getTokenSupplier().getThreadToken(); } private SecretKey generateKeyFromBits(byte[] bits, SymmetricKey.Type keyType) throws NoSuchAlgorithmException, TokenException, InvalidKeySpecException, InvalidAlgorithmParameterException { try { KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.PLAINTEXT); wrapper.initUnwrap(); SymmetricKey symk = wrapper.unwrapSymmetric(bits, keyType, 0); return new SecretKeyFacade(symk); } catch(InvalidKeyException e) { throw new InvalidKeySpecException(e.getMessage()); } } private static PBEKeyGenParams makePBEKeyGenParams(PBEKeySpec spec) throws InvalidKeySpecException { // The PBEKeySpec in JCE 1.2.1 does not contain salt or iteration. // The PBEKeySpec in JDK 1.4 does contain salt and iteration. // If this is a JCE 1.2.1 PBEKeySpec, we don't have enough // information and we have to throw an exception. If it's a JDK 1.4 // PBEKeySpec, we can get the information. The only way I know of // to find this out at runtime and be compatible with both // versions is to use the reflection API. Class specClass = spec.getClass(); try { Method getSaltMethod = specClass.getMethod("getSalt", (java.lang.Class[]) null); Method getIterationMethod = specClass.getMethod("getIterationCount", (java.lang.Class[]) null); byte[] salt = (byte[]) getSaltMethod.invoke(spec, (java.lang.Object[]) null); Integer itCountObj = (Integer) getIterationMethod.invoke(spec, (java.lang.Object[]) null); int iterationCount = itCountObj.intValue(); Password pass = new Password(spec.getPassword()); PBEKeyGenParams params = new PBEKeyGenParams(pass, salt, iterationCount); pass.clear(); return params; } catch(NoSuchMethodException nsme) { // fall through } catch(SecurityException se) { throw new InvalidKeySpecException( "SecurityException calling getMethod() on the key " + "spec's class: " + se.getMessage()); } catch(IllegalAccessException iae) { throw new InvalidKeySpecException( "IllegalAccessException invoking method on PBEKeySpec: " + iae.getMessage()); } catch(InvocationTargetException ite) { String message=""; Throwable t = ite.getTargetException(); if( t != null ) { message = t.getMessage(); } throw new InvalidKeySpecException( "InvocationTargetException invoking method on PBEKeySpec: "+ message); } throw new InvalidKeySpecException( "This version of PBEKeySpec is unsupported. It must " + "implement getSalt() and getIterationCount(). The PBEKeySpec in " + "JDK 1.4 works, as does org.mozilla.jss.crypto.PBEKeyGenParams. " + "The PBEKeySpec in JCE 1.2.1 and earlier does NOT work."); } @Override public SecretKey engineGenerateSecret(KeySpec spec) throws InvalidKeySpecException { try { if( spec instanceof PBEKeySpec || spec instanceof PBEKeyGenParams) { PBEKeyGenParams params; if( spec instanceof PBEKeySpec ) { params = makePBEKeyGenParams((PBEKeySpec)spec); } else { params = (org.mozilla.jss.crypto.PBEKeyGenParams) spec; } org.mozilla.jss.crypto.KeyGenerator gen =token.getKeyGenerator(alg); gen.initialize(params); SymmetricKey symk = gen.generate(); params.clear(); return new SecretKeyFacade(symk); } else if (spec instanceof DESedeKeySpec) { if( alg != KeyGenAlgorithm.DES3 ) { throw new InvalidKeySpecException( "Incorrect KeySpec type (" + spec.getClass().getName() + ") for algorithm (" + alg.toString() + ")"); } return generateKeyFromBits( ((DESedeKeySpec)spec).getKey(), SymmetricKey.Type.DES3 ); } else if (spec instanceof DESKeySpec) { if( alg != KeyGenAlgorithm.DES ) { throw new InvalidKeySpecException( "Incorrect KeySpec type (" + spec.getClass().getName() + ") for algorithm (" + alg.toString() + ")"); } return generateKeyFromBits( ((DESKeySpec)spec).getKey(), SymmetricKey.Type.DES ); } else if( spec instanceof SecretKeySpec ) { SecretKeySpec kspec = (SecretKeySpec) spec; SymmetricKey.Type type = SymmetricKey.Type.fromName( kspec.getAlgorithm()); return generateKeyFromBits( kspec.getEncoded(), type); } else { throw new InvalidKeySpecException( "Unsupported KeySpec: " + spec.getClass().getName()); } } catch(TokenException te) { throw new TokenRuntimeException(te.getMessage()); } catch(InvalidAlgorithmParameterException iape) { throw new InvalidKeySpecException( "InvalidAlgorithmParameterException: " + iape.getMessage()); } catch(IllegalStateException e) { throw (TokenRuntimeException) new TokenRuntimeException("IllegalStateException: " + e.getMessage()).initCause(e); } catch(CharConversionException e) { throw new InvalidKeySpecException("CharConversionException: " + e.getMessage(), e); } catch(NoSuchAlgorithmException e) { throw new InvalidKeySpecException("NoSuchAlgorithmException: " + e.getMessage(), e); } } @Override public KeySpec engineGetKeySpec(SecretKey key, Class keySpec) throws InvalidKeySpecException { try { if( ! (key instanceof SecretKeyFacade) ) { throw new InvalidKeySpecException("key is not a JSS key"); } SymmetricKey symkey = ((SecretKeyFacade)key).key; byte[] keyBits = symkey.getKeyData(); SymmetricKey.Type keyType = symkey.getType(); if( keySpec.equals(DESedeKeySpec.class) ) { if( keyType != SymmetricKey.Type.DES3 ) { throw new InvalidKeySpecException( "key/spec mismatch: " + keyType + " key, DESede spec"); } return new DESedeKeySpec(keyBits); } else if( keySpec.equals(DESKeySpec.class) ) { if( keyType != SymmetricKey.Type.DES ) { throw new InvalidKeySpecException( "key/spec mismatch: " + keyType + " key, DES spec"); } return new DESKeySpec(keyBits); } else if( keySpec.equals(SecretKeySpec.class) ) { return new SecretKeySpec(keyBits, keyType.toString()); } else { throw new InvalidKeySpecException( "Unsupported key spec: " + keySpec.getName()); } } catch(SymmetricKey.NotExtractableException e) { throw new InvalidKeySpecException("Key is not extractable: " + e.getMessage(), e); } catch(InvalidKeyException e) { // This gets thrown by the key spec constructor if there's something // wrong with the key bits. But since those key bits came from // a real key, this should never happen. throw new InvalidKeySpecException("Invalid key: " + e.getMessage(), e); } } @Override public SecretKey engineTranslateKey(SecretKey key) throws InvalidKeyException { if( key instanceof SecretKeyFacade ) { // try cloning the key try { SymmetricKey oldkey = ((SecretKeyFacade)key).key; CryptoToken owningToken = oldkey.getOwningToken(); org.mozilla.jss.crypto.KeyGenerator keygen = token.getKeyGenerator(oldkey.getType().getKeyGenAlg()); SymmetricKey newkey = keygen.clone(oldkey); return new SecretKeyFacade(newkey); } catch(SymmetricKey.NotExtractableException nee) { // no way around this, we fail throw new InvalidKeyException("key is not extractable"); } catch(TokenException te) { // fall through and try doing it the long way } catch(NoSuchAlgorithmException nsae) { throw new InvalidKeyException("Unsupported algorithm: " + nsae.getMessage()); } } // try extracting the key value and then creating a new key try { byte[] keyBits = key.getEncoded(); if( keyBits == null ) { throw new InvalidKeyException("Key is not extractable"); } SymmetricKey.Type keyType = SymmetricKey.Type.fromName( key.getAlgorithm() ); return generateKeyFromBits( keyBits, keyType); } catch( NoSuchAlgorithmException nsae ) { throw new InvalidKeyException("Unsupported algorithm: " + key.getAlgorithm()); } catch(TokenException te) { throw new InvalidKeyException("Token failed to process key: " + te.getMessage()); } catch(InvalidKeySpecException ikse) { throw new InvalidKeyException("Invalid key spec: " + ikse.getMessage()); } catch(InvalidAlgorithmParameterException iape) { throw new InvalidKeyException("Invalid algorithm parameters: " + iape.getMessage()); } } public static void main(String args[]) { try { CryptoManager.initialize("."); CryptoManager cm = CryptoManager.getInstance(); CryptoToken tok = cm.getInternalCryptoToken(); cm.setThreadToken(tok); org.mozilla.jss.crypto.KeyGenerator keygen = tok.getKeyGenerator(KeyGenAlgorithm.DES3); SymmetricKey symk = keygen.generate(); SecretKeyFacade origKey = new SecretKeyFacade(symk); JSSSecretKeyFactorySpi fact = new JSSSecretKeyFactorySpi(KeyGenAlgorithm.DES3); DESedeKeySpec kspec = (DESedeKeySpec) fact.engineGetKeySpec(origKey, DESedeKeySpec.class); SecretKeyFacade newKey = (SecretKeyFacade) fact.engineGenerateSecret(kspec); org.mozilla.jss.crypto.Cipher cipher = tok.getCipherContext(EncryptionAlgorithm.DES3_ECB); cipher.initEncrypt(origKey.key); String original = "Hello, World!!!!"; byte[] cipherText = cipher.doFinal( original.getBytes("UTF-8") ); System.out.println("ciphertext is " + cipherText.length + " bytes"); cipher.initDecrypt(newKey.key); byte[] plainText = cipher.doFinal(cipherText); System.out.println("recovered plaintext is " + plainText.length + " bytes"); String recovered = new String(plainText, "UTF-8"); System.out.println("Recovered '" + recovered + "'"); if( ! recovered.equals(original) ) { throw new Exception("recovered string is different from original"); } char[] pw = "foobarpw".toCharArray(); byte[] salt = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }; int iterationCount = 2; // generate a PBE key the old-fashioned way keygen = tok.getKeyGenerator(PBEAlgorithm.PBE_SHA1_DES3_CBC); PBEKeyGenParams jssKeySpec = new PBEKeyGenParams(pw, salt, iterationCount); keygen.initialize(jssKeySpec); symk = keygen.generate(); byte[] keydata = symk.getKeyData(); // generate a PBE key with the JCE SecretKeyFactory keyFact = SecretKeyFactory.getInstance("PBEWithSHA1AndDESede", "Mozilla-JSS"); newKey = (SecretKeyFacade) keyFact.generateSecret(jssKeySpec); byte[] newkeydata = newKey.key.getKeyData(); if( ! java.util.Arrays.equals(keydata, newkeydata) ) { throw new Exception("generated PBE keys are different"); } System.out.println("generated PBE keys are the same"); /* XXX JDK 1.4 ONLY // now try with a JDK 1.4 PBEKeySpec PBEKeySpec keySpec = new PBEKeySpec(pw, salt, iterationCount); newKey = (SecretKeyFacade) keyFact.generateSecret(keySpec); if( ! java.util.Arrays.equals(keydata, newKey.key.getKeyData()) ) { throw new Exception("generated PBE keys are different"); } System.out.println("generated PBE keys are the same"); */ System.exit(0); } catch(Throwable t) { t.printStackTrace(); System.exit(-1); } } public static class DES extends JSSSecretKeyFactorySpi { public DES() { super(KeyGenAlgorithm.DES); } } public static class DESede extends JSSSecretKeyFactorySpi { public DESede() { super(KeyGenAlgorithm.DESede); } } public static class AES extends JSSSecretKeyFactorySpi { public AES() { super(KeyGenAlgorithm.AES); } } public static class RC4 extends JSSSecretKeyFactorySpi { public RC4() { super(KeyGenAlgorithm.RC4); } } public static class RC2 extends JSSSecretKeyFactorySpi { public RC2() { super(KeyGenAlgorithm.RC2); } } public static class PBE_MD5_DES_CBC extends JSSSecretKeyFactorySpi { public PBE_MD5_DES_CBC() { super(PBEAlgorithm.PBE_MD5_DES_CBC); } } public static class PBE_SHA1_DES_CBC extends JSSSecretKeyFactorySpi { public PBE_SHA1_DES_CBC() { super(PBEAlgorithm.PBE_SHA1_DES_CBC); } } public static class PBE_SHA1_DES3_CBC extends JSSSecretKeyFactorySpi { public PBE_SHA1_DES3_CBC() { super(PBEAlgorithm.PBE_SHA1_DES3_CBC); } } public static class PBE_SHA1_RC4_128 extends JSSSecretKeyFactorySpi { public PBE_SHA1_RC4_128() { super(PBEAlgorithm.PBE_SHA1_RC4_128); } } public static class HmacSHA1 extends JSSSecretKeyFactorySpi { public HmacSHA1() { super(KeyGenAlgorithm.SHA1_HMAC); } } public static class PBAHmacSHA1 extends JSSSecretKeyFactorySpi { public PBAHmacSHA1() { super(KeyGenAlgorithm.PBA_SHA1_HMAC); } } public static class HmacSHA256 extends JSSSecretKeyFactorySpi { public HmacSHA256() { super(KeyGenAlgorithm.SHA256_HMAC); } } public static class HmacSHA384 extends JSSSecretKeyFactorySpi { public HmacSHA384() { super(KeyGenAlgorithm.SHA384_HMAC); } } public static class HmacSHA512 extends JSSSecretKeyFactorySpi { public HmacSHA512() { super(KeyGenAlgorithm.SHA512_HMAC); } } public static class GenericSecret extends JSSSecretKeyFactorySpi { public GenericSecret() { super(KeyGenAlgorithm.GENERIC_SECRET); } } } jss-5.0.0/src/main/java/org/mozilla/jss/provider/javax/crypto/JSSTokenKeyManager.java000066400000000000000000000110631412550063600305410ustar00rootroot00000000000000/* BEGIN COPYRIGHT BLOCK * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Copyright (C) 2017 Red Hat, Inc. * All rights reserved. * END COPYRIGHT BLOCK */ package org.mozilla.jss.provider.javax.crypto; import java.net.Socket; import java.security.KeyStore; import java.security.Principal; import java.security.PrivateKey; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collection; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.pkcs11.PK11Cert; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class JSSTokenKeyManager implements JSSKeyManager { final static Logger logger = LoggerFactory.getLogger(JSSTokenKeyManager.class); private KeyStore jks; private CryptoManager cm; private char[] password; public JSSTokenKeyManager(KeyStore jssKeyStore, char[] password) { jks = jssKeyStore; this.password = password; try { cm = CryptoManager.getInstance(); } catch (NotInitializedException nie) { String msg = "CryptoManager reported as not initialized but have "; msg += "a working KeyStore instance! " + nie.getMessage(); throw new RuntimeException(msg, nie); } } @Override public String chooseClientAlias(String[] keyTypes, Principal[] issuers, Socket socket) { logger.debug("JSSKeyManager: chooseClientAlias() - not implemented"); return null; } @Override public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) { logger.debug("JSSKeyManager: chooseServerAlias() - not implemented"); return null; } @Override public org.mozilla.jss.crypto.X509Certificate getCertificate(String alias) { try { if (jks == null) { return cm.findCertByNickname(alias); } return (org.mozilla.jss.crypto.X509Certificate) jks.getCertificate(alias); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public X509Certificate[] getCertificateChain(String alias) { logger.debug("JSSKeyManager: getCertificateChain(" + alias + ")"); try { org.mozilla.jss.crypto.X509Certificate cert = getCertificate(alias); org.mozilla.jss.crypto.X509Certificate[] chain = cm.buildCertificateChain(cert); logger.debug("JSSKeyManager: cert chain:"); Collection list = new ArrayList<>(); for (org.mozilla.jss.crypto.X509Certificate c : chain) { logger.debug("JSSKeyManager: - " + c.getSubjectDN()); list.add((PK11Cert) c); } return list.toArray(new X509Certificate[list.size()]); } catch (Throwable e) { logger.error(e.getMessage(), e); throw new RuntimeException(e); } } @Override public String[] getClientAliases(String keyType, Principal[] issuers) { logger.debug("JSSKeyManager: getClientAliases() - not implemented"); return null; } @Override public PrivateKey getPrivateKey(String alias) { logger.debug("JSSKeyManager: getPrivateKey(" + alias + ")"); try { if (jks == null) { try (PK11Cert cert = (PK11Cert) cm.findCertByNickname(alias)) { PrivateKey key = cm.findPrivKeyByCert(cert); return key; } } return (PrivateKey) jks.getKey(alias, password); } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } @Override public String[] getServerAliases(String keyType, Principal[] issuers) { logger.debug("JSSKeyManager: getServerAliases() - not implemented"); return null; } } jss-5.0.0/src/main/java/org/mozilla/jss/provider/javax/crypto/JSSTrustManager.java000066400000000000000000000201201412550063600301230ustar00rootroot00000000000000/* BEGIN COPYRIGHT BLOCK * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Copyright (C) 2017 Red Hat, Inc. * All rights reserved. * END COPYRIGHT BLOCK */ package org.mozilla.jss.provider.javax.crypto; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import javax.net.ssl.X509TrustManager; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.pkcs11.PK11Cert; import org.mozilla.jss.netscape.security.util.Cert; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class JSSTrustManager implements X509TrustManager { final static Logger logger = LoggerFactory.getLogger(JSSTrustManager.class); final static String SERVER_AUTH_OID = "1.3.6.1.5.5.7.3.1"; final static String CLIENT_AUTH_OID = "1.3.6.1.5.5.7.3.2"; public boolean allowMissingExtendedKeyUsage = false; public void configureAllowMissingExtendedKeyUsage(boolean allow) { allowMissingExtendedKeyUsage = allow; } public void checkCertChain(X509Certificate[] certChain, String keyUsage) throws Exception { logger.debug("JSSTrustManager: checkCertChain(" + keyUsage + ")"); // sort cert chain from root to leaf certChain = Cert.sortCertificateChain(certChain); for (X509Certificate cert : certChain) { logger.debug("JSSTrustManager: - " + cert.getSubjectDN()); } // get CA certs X509Certificate[] caCerts = getAcceptedIssuers(); // validating cert chain from root to leaf for (int i = 0; i < certChain.length; i++) { X509Certificate cert = certChain[i]; // validating key usage on leaf cert only String usage; if (i == certChain.length - 1) { usage = keyUsage; } else { usage = null; } checkCert(cert, caCerts, usage); // use the current cert as the CA cert for the next cert in the chain caCerts = new X509Certificate[] { cert }; } } public void checkCert(X509Certificate cert, X509Certificate[] caCerts, String keyUsage) throws Exception { logger.debug("JSSTrustManager: checkCert(" + cert.getSubjectDN() + "):"); boolean[] aki = cert.getIssuerUniqueID(); logger.debug("JSSTrustManager: cert AKI: " + Arrays.toString(aki)); X509Certificate issuer = null; for (X509Certificate caCert : caCerts) { boolean[] ski = caCert.getSubjectUniqueID(); logger.debug("JSSTrustManager: SKI of " + caCert.getSubjectDN() + ": " + Arrays.toString(ski)); try { cert.verify(caCert.getPublicKey(), "Mozilla-JSS"); issuer = caCert; break; } catch (Exception e) { logger.debug("JSSTrustManager: invalid certificate: " + e); } } if (issuer == null) { throw new CertificateException("Unable to validate signature: " + cert.getSubjectDN()); } logger.debug("JSSTrustManager: cert signed by " + issuer.getSubjectDN()); logger.debug("JSSTrustManager: checking validity range:"); logger.debug("JSSTrustManager: - not before: " + cert.getNotBefore()); logger.debug("JSSTrustManager: - not after: " + cert.getNotAfter()); cert.checkValidity(); if (keyUsage != null) { List extendedKeyUsages = cert.getExtendedKeyUsage(); logger.debug("JSSTrustManager: checking extended key usages:"); if (extendedKeyUsages != null) { for (String extKeyUsage : extendedKeyUsages) { logger.debug("JSSTrustManager: - " + extKeyUsage); } } boolean haveKeyUsage = extendedKeyUsages != null && extendedKeyUsages.contains(keyUsage); boolean allowedToSkip = extendedKeyUsages == null && allowMissingExtendedKeyUsage; if (haveKeyUsage) { logger.debug("JSSTrustManager: extended key usage found: " + keyUsage); } else if (allowedToSkip) { logger.debug("JSSTrustManager: configured to allow null extended key usages field"); } else { String msg = "Missing EKU: " + keyUsage + ". Certificate with subject DN `" + cert.getSubjectDN() + "` had "; if (extendedKeyUsages == null) { msg += "no EKU extension"; } else { msg += "EKUs { "; boolean first = true; for (String eku : extendedKeyUsages) { if (!first) msg += " , "; msg += eku; first = false; } msg += " }"; } msg += ". class = " + cert.getClass(); throw new CertificateException(msg); } } } @Override public void checkClientTrusted(X509Certificate[] certChain, String authType) throws CertificateException { logger.debug("JSSTrustManager: checkClientTrusted(" + authType + "):"); try { checkCertChain(certChain, CLIENT_AUTH_OID); logger.debug("JSSTrustManager: SSL client certificate is valid"); } catch (CertificateException e) { logger.warn("JSSTrustManager: Invalid SSL client certificate: " + e); throw e; } catch (Exception e) { logger.warn("JSSTrustManager: Unable to validate certificate: " + e); throw new CertificateException(e); } } @Override public void checkServerTrusted(X509Certificate[] certChain, String authType) throws CertificateException { logger.debug("JSSTrustManager: checkServerTrusted(" + certChain.length + ", " + authType + "):"); try { checkCertChain(certChain, SERVER_AUTH_OID); logger.debug("JSSTrustManager: SSL server certificate is valid"); } catch (CertificateException e) { logger.warn("JSSTrustManager: Invalid SSL server certificate: " + e); throw e; } catch (Exception e) { logger.warn("JSSTrustManager: Unable to validate SSL server certificate: " + e); throw new CertificateException(e); } } @Override public X509Certificate[] getAcceptedIssuers() { logger.debug("JSSTrustManager: getAcceptedIssuers():"); Collection caCerts = new ArrayList<>(); try { CryptoManager manager = CryptoManager.getInstance(); for (org.mozilla.jss.crypto.X509Certificate cert : manager.getCACerts()) { logger.debug("JSSTrustManager: - " + cert.getSubjectDN()); try { PK11Cert caCert = (PK11Cert) cert; caCert.checkValidity(); caCerts.add(caCert); } catch (Exception e) { logger.debug("JSSTrustManager: invalid CA certificate: " + e); } } } catch (NotInitializedException e) { logger.error("JSSTrustManager: Unable to get CryptoManager: " + e, e); throw new RuntimeException(e); } return caCerts.toArray(new X509Certificate[caCerts.size()]); } } jss-5.0.0/src/main/java/org/mozilla/jss/provider/javax/crypto/JSSTrustManagerFactory.java000066400000000000000000000011201412550063600314520ustar00rootroot00000000000000package org.mozilla.jss.provider.javax.crypto; import java.security.*; import javax.net.ssl.*; public class JSSTrustManagerFactory extends TrustManagerFactorySpi { @Override protected void engineInit(KeyStore ks) { // There is nothing we can do here. } @Override protected void engineInit(ManagerFactoryParameters spec) { // There is nothing we can do here. } @Override protected TrustManager[] engineGetTrustManagers() { TrustManager[] tms = new TrustManager[1]; tms[0] = new JSSTrustManager(); return tms; } } jss-5.0.0/src/main/java/org/mozilla/jss/provider/javax/net/000077500000000000000000000000001412550063600235375ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/provider/javax/net/JSSContextSpi.java000066400000000000000000000102731412550063600270650ustar00rootroot00000000000000package org.mozilla.jss.provider.javax.net; import java.security.*; import java.util.ArrayList; import javax.net.ssl.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.mozilla.jss.provider.javax.crypto.JSSKeyManager; import org.mozilla.jss.ssl.javax.JSSEngine; import org.mozilla.jss.ssl.javax.JSSEngineReferenceImpl; import org.mozilla.jss.ssl.javax.JSSParameters; import org.mozilla.jss.ssl.javax.JSSServerSocketFactory; import org.mozilla.jss.ssl.javax.JSSSocketFactory; import org.mozilla.jss.ssl.SSLVersion; public class JSSContextSpi extends SSLContextSpi { public static Logger logger = LoggerFactory.getLogger(JSSContextSpi.class); JSSKeyManager key_manager; X509TrustManager[] trust_managers; SSLVersion protocol_version; @Override public void engineInit(KeyManager[] kms, TrustManager[] tms, SecureRandom sr) throws KeyManagementException { logger.debug("JSSContextSpi.engineInit(" + kms + ", " + tms + ", " + sr + ")"); if (kms != null) { for (KeyManager km : kms) { if (km instanceof JSSKeyManager) { key_manager = (JSSKeyManager) km; break; } } } if (tms != null) { ArrayList xtms = new ArrayList(); for (TrustManager tm : tms) { if (tm instanceof X509TrustManager) { xtms.add((X509TrustManager) tm); } } trust_managers = xtms.toArray(new X509TrustManager[xtms.size()]); } } @Override public SSLEngine engineCreateSSLEngine() { logger.debug("JSSContextSpi.engineCreateSSLEngine()"); JSSEngine ret = new JSSEngineReferenceImpl(); initializeEngine(ret); return ret; } @Override public SSLEngine engineCreateSSLEngine(String host, int port) { logger.debug("JSSContextSpi.engineCreateSSLEngine(" + host + ", " + port + ")"); JSSEngine ret = new JSSEngineReferenceImpl(host, port); initializeEngine(ret); return ret; } private void initializeEngine(JSSEngine eng) { eng.setKeyManager(key_manager); eng.setTrustManagers(trust_managers); if (protocol_version != null) { eng.setEnabledProtocols(protocol_version, protocol_version); } } @Override public SSLSessionContext engineGetClientSessionContext() { logger.debug("JSSContextSpi.engineGetClientSessionContext() - not implemented"); return null; } @Override public SSLSessionContext engineGetServerSessionContext() { logger.debug("JSSContextSpi.engineGetServerSessionContext() - not implemented"); return null; } @Override public SSLServerSocketFactory engineGetServerSocketFactory() { String protocol = "TLS"; if (protocol_version != null) { protocol = protocol_version.jdkAlias(); } logger.debug("JSSContextSpi.engineGetServerSocketFactory() @ " + protocol); return new JSSServerSocketFactory(protocol, key_manager, trust_managers); } @Override public SSLSocketFactory engineGetSocketFactory() { String protocol = "TLS"; if (protocol_version != null) { protocol = protocol_version.jdkAlias(); } logger.debug("JSSContextSpi.engineGetSocketFactory() @ " + protocol); return new JSSSocketFactory(protocol, key_manager, trust_managers); } @Override public SSLParameters engineGetSupportedSSLParameters() { JSSParameters params = new JSSParameters(); params.setCipherSuites(JSSEngine.queryEnabledCipherSuites()); params.setProtocols(JSSEngine.queryEnabledProtocols()); return params; } public class TLSv11 extends JSSContextSpi { public TLSv11() { protocol_version = SSLVersion.TLS_1_1; } } public class TLSv12 extends JSSContextSpi { public TLSv12() { protocol_version = SSLVersion.TLS_1_2; } } public class TLSv13 extends JSSContextSpi { public TLSv13() { protocol_version = SSLVersion.TLS_1_3; } } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/000077500000000000000000000000001412550063600206075ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/ssl/CipherPolicy.java000066400000000000000000000012511412550063600240430ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.ssl; public class CipherPolicy { public static final CipherPolicy DOMESTIC = new CipherPolicy(SocketBase.SSL_POLICY_DOMESTIC); public static final CipherPolicy EXPORT = new CipherPolicy(SocketBase.SSL_POLICY_EXPORT); public static final CipherPolicy FRANCE = new CipherPolicy(SocketBase.SSL_POLICY_FRANCE); private int _enum; private CipherPolicy(int _enum) { } int getEnum() { return _enum; } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/PrintOutputStreamWriter.java000066400000000000000000000013221412550063600263360ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // // // // $Id$ package org.mozilla.jss.ssl; import java.io.*; class PrintOutputStreamWriter extends java.io.OutputStreamWriter { public PrintOutputStreamWriter(OutputStream out) { super(out); } public void print(String x) throws java.io.IOException { write(x, 0, x.length()); } public void println(String x) throws java.io.IOException { // String line = new String(x + "\n"); String line = x + "\n"; write(line, 0, line.length()); flush(); } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLAlertDescription.java000066400000000000000000000071221412550063600253110ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.ssl; import javax.net.ssl.SSLException; import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLPeerUnverifiedException; import javax.net.ssl.SSLProtocolException; public enum SSLAlertDescription { // see lib/ssl/ssl3prot.h in NSS CLOSE_NOTIFY (0), END_OF_EARLY_DATA (1), // TLS 1.3 UNEXPECTED_MESSAGE (10, SSLProtocolException.class), BAD_RECORD_MAC (20, SSLProtocolException.class), DECRYPTION_FAILED (21, SSLProtocolException.class), // RFC 5246 RECORD_OVERFLOW (22, SSLProtocolException.class), // TLS only DECOMPRESSION_FAILURE (30, SSLProtocolException.class), HANDSHAKE_FAILURE (40, SSLHandshakeException.class), NO_CERTIFICATE (41, SSLPeerUnverifiedException.class), // SSL3 only, NOT TLS BAD_CERTIFICATE (42, SSLPeerUnverifiedException.class), UNSUPPORTED_CERTIFICATE (43, SSLPeerUnverifiedException.class), CERTIFICATE_REVOKED (44, SSLPeerUnverifiedException.class), CERTIFICATE_EXPIRED (45, SSLPeerUnverifiedException.class), CERTIFICATE_UNKNOWN (46, SSLPeerUnverifiedException.class), ILLEGAL_PARAMETER (47, SSLProtocolException.class), // All alerts below are TLS only. UNKNOWN_CA (48, SSLPeerUnverifiedException.class), ACCESS_DENIED (49, SSLHandshakeException.class), DECODE_ERROR (50, SSLProtocolException.class), DECRYPT_ERROR (51, SSLProtocolException.class), EXPORT_RESTRICTION (60, SSLHandshakeException.class), PROTOCOL_VERSION (70, SSLHandshakeException.class), INSUFFICIENT_SECURITY (71, SSLHandshakeException.class), INTERNAL_ERROR (80, SSLProtocolException.class), INAPPROPRIATE_FALLBACK (86, SSLProtocolException.class), // could also be sent for SSLv3 USER_CANCELED (90, SSLProtocolException.class), NO_RENEGOTIATION (100, SSLHandshakeException.class), // Alerts for client hello extensions MISSING_EXTENSION (109, SSLHandshakeException.class), UNSUPPORTED_EXTENSION (110, SSLHandshakeException.class), CERTIFICATE_UNOBTAINABLE (111, SSLPeerUnverifiedException.class), UNRECOGNIZED_NAME (112, SSLHandshakeException.class), BAD_CERTIFICATE_STATUS_RESPONSE (113, SSLPeerUnverifiedException.class), BAD_CERTIFICATE_HASH_VALUE (114, SSLPeerUnverifiedException.class), NO_APPLICATION_PROTOCOL (120, SSLHandshakeException.class); private int id; private Class exception; private SSLAlertDescription(int id) { this.id = id; } private SSLAlertDescription(int id, Class exception) { this(id); this.exception = exception; } public int getID() { return id; } public Class getExceptionClass() { return exception; } public static SSLAlertDescription valueOf(int id) { for (SSLAlertDescription description : SSLAlertDescription.class.getEnumConstants()) { if (description.id == id) return description; } return null; } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLAlertEvent.java000066400000000000000000000066411412550063600241140ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.ssl; import java.util.EventObject; import javax.net.ssl.SSLException; import org.mozilla.jss.nss.SSLFDProxy; public class SSLAlertEvent extends EventObject { private static final long serialVersionUID = 1L; int level; int description; SSLAlertLevel levelEnum; SSLAlertDescription descriptionEnum; public SSLAlertEvent(SSLSocket socket) { super(socket); } public SSLAlertEvent(SSLSocket socket, int level, int description) { super(socket); setLevel(level); setDescription(description); } public SSLAlertEvent(SSLSocket socket, SSLAlertLevel level, SSLAlertDescription description) { super(socket); setLevel(level); setDescription(description); } public SSLAlertEvent(SSLFDProxy proxy) { super(proxy); } public SSLAlertEvent(SSLFDProxy proxy, int level, int description) { super(proxy); setLevel(level); setDescription(description); } public SSLAlertEvent(SSLFDProxy proxy, SSLAlertLevel level, SSLAlertDescription description) { super(proxy); setLevel(level); setDescription(description); } public SSLSocket getSocket() { return (SSLSocket) getSource(); } public SSLFDProxy getFileDesc() { return (SSLFDProxy) getSource(); } public int getLevel() { return level; } public SSLAlertLevel getLevelEnum() { return levelEnum; } public void setLevel(int level) { this.level = level; this.levelEnum = SSLAlertLevel.valueOf(level); } public void setLevel(SSLAlertLevel level) { this.levelEnum = level; this.level = level.getID(); } public int getDescription() { return description; } public SSLAlertDescription getDescriptionEnum() { return descriptionEnum; } public void setDescription(int description) { this.description = description; this.descriptionEnum = SSLAlertDescription.valueOf(description); } public void setDescription(SSLAlertDescription description) { this.descriptionEnum = description; this.description = description.getID(); } public SSLException toException() { if (levelEnum == SSLAlertLevel.FATAL) { Class exception_class = descriptionEnum.getExceptionClass(); SSLException exception; try { exception = exception_class.getConstructor(String.class).newInstance(this.toString()); } catch (Exception e) { // When we fail to construct an exception of type // exception_class, usually that means that we've gotten // a null exception_class. In which case, because this is // a fatal exception, throw it as a generic SSLException. exception = new SSLException(this.toString()); } return exception; } return null; } public void throwException() throws SSLException { throw this.toException(); } @Override public String toString() { return this.levelEnum + ": " + this.descriptionEnum; } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLAlertLevel.java000066400000000000000000000012561412550063600240770ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.ssl; public enum SSLAlertLevel { // see lib/ssl/ssl3prot.h in NSS WARNING (1), FATAL (2); private int id; private SSLAlertLevel(int id) { this.id = id; } public int getID() { return id; } public static SSLAlertLevel valueOf(int id) { for (SSLAlertLevel level : SSLAlertLevel.class.getEnumConstants()) { if (level.id == id) return level; } return null; } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLAuthType.java000066400000000000000000000013201412550063600235730ustar00rootroot00000000000000package org.mozilla.jss.ssl; public enum SSLAuthType { ssl_auth_null (0), ssl_auth_rsa_decrypt (1), ssl_auth_dsa (2), ssl_auth_kea (3), ssl_auth_ecdsa (4), ssl_auth_ecdh_rsa (5), ssl_auth_ecdh_ecdsa (6), ssl_auth_rsa_sign (7), ssl_auth_rsa_pss (8), ssl_auth_psk (9), ssl_auth_tls13_any (10); private int value; private SSLAuthType(int value) { this.value = value; } public int getValue() { return value; } public static SSLAuthType valueOf(int value) { for (SSLAuthType type : SSLAuthType.values()) { if (type.value == value) { return type; } } return null; } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLCertificateApprovalCallback.java000066400000000000000000000140421412550063600274010ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * SSLSecurityStatus.java * */ package org.mozilla.jss.ssl; import java.util.Enumeration; import java.util.Vector; import org.mozilla.jss.pkcs11.PK11Cert; /** * This interface is what you should implement if you want to * be able to decide whether or not you want to approve the peer's cert, * instead of having NSS do that. */ public interface SSLCertificateApprovalCallback { /** * This method is called when the server sends it's certificate to * the client. * * The 'status' argument passed to this method is constructed by * NSS. It's a list of things 'wrong' with the certificate (which * you can see by calling the status.getReasons() method. So, * if there are problems regarding validity or trust of any of the * certificates in the chain, you can present this info to the user. * * If there are no items in the Enumeration returned by getReasons(), * you can assume that the certificate is trustworthy, and return * true, or you can continue to make further tests of your own * to determine trustworthiness. * * @param cert the peer's server certificate * @param status the ValidityStatus object containing a list * of all the problems with the cert * * @return true allow the connection to continue
* false terminate the connection (Expect an IOException * on the outstanding read()/write() on the socket) */ public boolean approve(org.mozilla.jss.crypto.X509Certificate cert, ValidityStatus status); /** * This class holds details about the errors for each cert in * the chain that the server presented * * To use this class, getReasons(), then iterate over the enumeration */ class ValidityStatus { public static final int EXPIRED_CERTIFICATE = -8192 + 11; public static final int REVOKED_CERTIFICATE = -8192 + 12; public static final int INADEQUATE_KEY_USAGE = -8192 + 90; public static final int INADEQUATE_CERT_TYPE = -8192 + 91; public static final int UNTRUSTED_CERT = -8192 + 21; public static final int CERT_STATUS_SERVER_ERROR = -8192 +115; public static final int UNKNOWN_ISSUER = -8192 + 13; public static final int UNTRUSTED_ISSUER = -8192 + 20; public static final int CERT_NOT_IN_NAME_SPACE = -8192 + 112; public static final int CA_CERT_INVALID = -8192 + 36; public static final int PATH_LEN_CONSTRAINT_INVALID = -8192 + 37; public static final int BAD_KEY = -8192 + 14; public static final int BAD_SIGNATURE = -8192 + 10; public static final int EXPIRED_ISSUER_CERTIFICATE = -8192 +30; public static final int INVALID_TIME = -8192 + 8; public static final int UNKNOWN_SIGNER = -8192 + 116; public static final int SEC_ERROR_CRL_EXPIRED = -8192 + 31; public static final int SEC_ERROR_CRL_BAD_SIGNATURE = -8192 + 32; public static final int SEC_ERROR_CRL_INVALID = -8192 + 33; public static final int CERT_BAD_ACCESS_LOCATION = -8192 + 117; public static final int OCSP_UNKNOWN_RESPONSE_TYPE = -8192 + 118; public static final int OCSP_BAD_HTTP_RESPONSE = -8192 + 119; public static final int OCSP_MALFORMED_REQUEST = -8192 + 120; public static final int OCSP_SERVER_ERROR = -8192 + 121; public static final int OCSP_TRY_SERVER_LATER = -8192 + 122; public static final int OCSP_REQUEST_NEEDS_SIG = -8192 + 123; public static final int OCSP_UNAUTHORIZED_REQUEST = -8192 + 124; public static final int OCSP_UNKNOWN_RESPONSE_STATUS= -8192 + 125; public static final int OCSP_UNKNOWN_CERT = -8192 + 126; public static final int OCSP_NOT_ENABLED = -8192 + 127; public static final int OCSP_NO_DEFAULT_RESPONDER = -8192 + 128; public static final int OCSP_MALFORMED_RESPONSE = -8192 + 129; public static final int OCSP_UNAUTHORIZED_RESPONSE = -8192 + 130; public static final int OCSP_FUTURE_RESPONSE = -8192 + 131; public static final int OCSP_OLD_RESPONSE = -8192 + 132; /** this indicates common-name mismatch */ public static final int BAD_CERT_DOMAIN = -12288 + 12; private Vector reasons = new Vector<>(); /** * add a new failure reason to this enumeration. This is called from the * native code callback when it does a verify on the cert chain * * @param newReason sslerr.h error code - see constants defined above; * @param cert a reference to the cert - so you can see the subject name, etc * @param depth the index of this cert in the chain. 0 is the server cert. */ public void addReason(int newReason, PK11Cert cert, int depth) { ValidityItem status = new ValidityItem(newReason,cert,depth); reasons.addElement(status); } /** * returns an enumeration. The elements in the enumeration are * all of type 'ValidityItem' */ public Enumeration getReasons() { return reasons.elements(); } } class ValidityItem { private int reason; private int depth; private PK11Cert cert; public ValidityItem(int reason, PK11Cert cert, int depth) { this.reason = reason; this.cert = cert; this.depth = depth; } /** * @return the NSS error code which caused the error - see the list of * error codes above for those which could be returned */ public int getReason() { return reason; } /** * @return the index into the cert chain of the certificate which caused * this error. In a chain 5-certs long, 0 is the server-cert. * 1,2,3 would be the intermediates, and 4 would be the root */ public int getDepth() { return depth; } /** * @return the certificate associated with this error. You can use * the X509Certificate functions to get details such as issuer/subject * name, serial number, etc. */ public PK11Cert getCert() { return cert; } } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLCipher.c000066400000000000000000000116311412550063600225510ustar00rootroot00000000000000#include #include #include #include #include #include "_jni/org_mozilla_jss_ssl_SSLCipher.h" #include "jssconfig.h" /* Copied from NSS's ssl3con.c. */ static const CK_MECHANISM_TYPE auth_alg_defs[] = { CKM_INVALID_MECHANISM, /* ssl_auth_null */ CKM_RSA_PKCS, /* ssl_auth_rsa_decrypt */ CKM_DSA, /* ? _SHA1 */ /* ssl_auth_dsa */ CKM_INVALID_MECHANISM, /* ssl_auth_kea (unused) */ CKM_ECDSA, /* ssl_auth_ecdsa */ CKM_ECDH1_DERIVE, /* ssl_auth_ecdh_rsa */ CKM_ECDH1_DERIVE, /* ssl_auth_ecdh_ecdsa */ CKM_RSA_PKCS, /* ssl_auth_rsa_sign */ CKM_RSA_PKCS_PSS, /* ssl_auth_rsa_pss */ CKM_NSS_HKDF_SHA256, /* ssl_auth_psk (just check for HKDF) */ CKM_INVALID_MECHANISM /* ssl_auth_tls13_any */ }; PR_STATIC_ASSERT(PR_ARRAY_SIZE(auth_alg_defs) == ssl_auth_size); /* Copied from NSS's ssl3con.c. */ static const CK_MECHANISM_TYPE kea_alg_defs[] = { CKM_INVALID_MECHANISM, /* ssl_kea_null */ CKM_RSA_PKCS, /* ssl_kea_rsa */ CKM_DH_PKCS_DERIVE, /* ssl_kea_dh */ CKM_INVALID_MECHANISM, /* ssl_kea_fortezza (unused) */ CKM_ECDH1_DERIVE, /* ssl_kea_ecdh */ CKM_ECDH1_DERIVE, /* ssl_kea_ecdh_psk */ CKM_DH_PKCS_DERIVE, /* ssl_kea_dh_psk */ CKM_INVALID_MECHANISM, /* ssl_kea_tls13_any */ }; PR_STATIC_ASSERT(PR_ARRAY_SIZE(kea_alg_defs) == ssl_kea_size); #ifdef HAVE_NSS_CIPHER_SUITE_INFO_KDFHASH /* Not present in ssl3con.c. */ static const CK_MECHANISM_TYPE hash_alg_defs[] = { CKM_INVALID_MECHANISM, /* ssl_hash_none */ CKM_MD5, /* ssl_hash_md5 */ CKM_SHA_1, /* ssl_hash_sha1 */ CKM_SHA224, /* ssl_hash_sha224 */ CKM_SHA256, /* ssl_hash_sha256 */ CKM_SHA384, /* ssl_hash_sha384 */ CKM_SHA512, /* ssl_hash_sha512 */ }; #endif JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_ssl_SSLCipher_checkSupportedStatus(JNIEnv *env, jclass clazz, jint cipher_suite) { PRInt32 allowed; SSLCipherSuiteInfo info = { 0 }; /* Fetch information about whether or not this cipher is allowed by local * policy. */ if (SSL_CipherPolicyGet(cipher_suite, &allowed) != SECSuccess) { /* When the previous call fails, it means that the specified cipher * suite wasn't found; calls to enable it will also fail. Mark it as * unsupported. */ return JNI_FALSE; } if (allowed != SSL_ALLOWED) { /* If the cipher suite isn't allowed by policy, reject it early. */ return JNI_FALSE; } /* Fetch extended information about this particular cipher suite. */ if (SSL_GetCipherSuiteInfo(cipher_suite, &info, sizeof(info)) != SECSuccess) { /* Since we know the cipher suite is good (because the call to * SSL_CipherPolicyGet(...) succeeded), we know that this is because * the size of SSLCipherSuiteInfo in the version of NSS that we * were compiled with exceeds the size of the SSLCipherSuiteInfo * struct available to NSS at runtime. * * This happens *only* when the version of NSS we were compiled with * is *newer* than what is on the system. * * This is a "soft" failure and means that we have to rely only on * cipher policy to tell if this cipher is supported. Since it was * allowed, return JNI_TRUE here. */ return JNI_TRUE; } /* Our NSS DB or application could've configured FIPS mode explicitly, * even though the system might not be in FIPS mode. In that case, * explicitly check that this allowed cipher is available in FIPS mode. */ if (PK11_IsFIPS() && info.isFIPS == 0) { return JNI_FALSE; } /* Our last checks are to make sure that, for all related mechanisms, we * have a token with this function. This is similar to the code in NSS's * ssl3_config_match_init(...). Note that this doesn't finish the work * of that function (by checking that the certificate matches the cipher * suite). */ if (info.authType != ssl_auth_tls13_any && info.authType != ssl_auth_null && !PK11_TokenExists(auth_alg_defs[info.authType])) { return JNI_FALSE; } if (info.keaType != ssl_kea_null && info.keaType != ssl_kea_tls13_any && !PK11_TokenExists(kea_alg_defs[info.keaType])) { return JNI_FALSE; } /* Only check if NSS >= 3.43 or if this feature was backported. Note that * when this condition holds at compile time, and we're executing under * an older NSS version, we'd have exited due to the check in * SSL_GetCipherSuiteInfo(...). That means that the value read here is * always correct. */ #ifdef HAVE_NSS_CIPHER_SUITE_INFO_KDFHASH if (info.kdfHash != ssl_hash_none && !PK11_TokenExists(hash_alg_defs[info.kdfHash])) { return JNI_FALSE; } #endif return JNI_TRUE; } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLCipher.java000066400000000000000000000613061412550063600232540ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.ssl; /** * SSL cipher. */ public enum SSLCipher { /** * * Note the following cipher-suites constants are not all implemented. * You need to call SSLSocket.getImplementedCiphersuites(). * */ SSL2_RC4_128_WITH_MD5 (0xFF01, SSLVersion.SSL_2_0), SSL2_RC4_128_EXPORT40_WITH_MD5 (0xFF02, SSLVersion.SSL_2_0), SSL2_RC2_128_CBC_WITH_MD5 (0xFF03, SSLVersion.SSL_2_0), SSL2_RC2_128_CBC_EXPORT40_WITH_MD5 (0xFF04, SSLVersion.SSL_2_0), SSL2_IDEA_128_CBC_WITH_MD5 (0xFF05, SSLVersion.SSL_2_0), SSL2_DES_64_CBC_WITH_MD5 (0xFF06, SSLVersion.SSL_2_0), SSL2_DES_192_EDE3_CBC_WITH_MD5 (0xFF07, SSLVersion.SSL_2_0), TLS_NULL_WITH_NULL_NULL (0x0000, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), /** * @deprecated Replaced with TLS_RSA_WITH_NULL_MD5. */ @Deprecated SSL3_RSA_WITH_NULL_MD5 (0x0001, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_RSA_WITH_NULL_MD5 (0x0001, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), /** * @deprecated Replaced with TLS_RSA_WITH_NULL_SHA. */ @Deprecated SSL3_RSA_WITH_NULL_SHA (0x0002, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_RSA_WITH_NULL_SHA (0x0002, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), SSL3_RSA_EXPORT_WITH_RC4_40_MD5 (0x0003, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), TLS_RSA_EXPORT_WITH_RC4_40_MD5 (0x0003, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), /** * @deprecated Replaced with TLS_RSA_WITH_RC4_128_MD5. */ @Deprecated SSL3_RSA_WITH_RC4_128_MD5 (0x0004, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_RSA_WITH_RC4_128_MD5 (0x0004, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), /** * @deprecated Replaced with TLS_RSA_WITH_RC4_128_SHA. */ @Deprecated SSL3_RSA_WITH_RC4_128_SHA (0x0005, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_RSA_WITH_RC4_128_SHA (0x0005, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5 (0x0006, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 (0x0006, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), /** * @deprecated Replaced with TLS_RSA_WITH_IDEA_CBC_SHA. */ @Deprecated SSL3_RSA_WITH_IDEA_CBC_SHA (0x0007, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1 }), TLS_RSA_WITH_IDEA_CBC_SHA (0x0007, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1 }), SSL3_RSA_EXPORT_WITH_DES40_CBC_SHA (0x0008, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), TLS_RSA_EXPORT_WITH_DES40_CBC_SHA (0x0008, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), /** * @deprecated Replaced with TLS_RSA_WITH_DES_CBC_SHA. */ @Deprecated SSL3_RSA_WITH_DES_CBC_SHA (0x0009, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1 }), TLS_RSA_WITH_DES_CBC_SHA (0x0009, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1 }), /** * @deprecated Replaced with TLS_RSA_WITH_3DES_EDE_CBC_SHA. */ @Deprecated SSL3_RSA_WITH_3DES_EDE_CBC_SHA (0x000a, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000a, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), SSL3_DH_DSS_EXPORT_WITH_DES40_CBC_SHA (0x000b, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA (0x000b, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), /** * @deprecated Replaced with TLS_DH_DSS_WITH_DES_CBC_SHA. */ @Deprecated SSL3_DH_DSS_WITH_DES_CBC_SHA (0x000c, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1 }), TLS_DH_DSS_WITH_DES_CBC_SHA (0x000c, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1 }), /** * @deprecated Replaced with TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA. */ @Deprecated SSL3_DH_DSS_WITH_3DES_EDE_CBC_SHA (0x000d, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA (0x000d, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), SSL3_DH_RSA_EXPORT_WITH_DES40_CBC_SHA (0x000e, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA (0x000e, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), /** * @deprecated Replaced with TLS_DH_RSA_WITH_DES_CBC_SHA. */ @Deprecated SSL3_DH_RSA_WITH_DES_CBC_SHA (0x000f, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1 }), TLS_DH_RSA_WITH_DES_CBC_SHA (0x000f, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1 }), /** * @deprecated Replaced with TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA. */ @Deprecated SSL3_DH_RSA_WITH_3DES_EDE_CBC_SHA (0x0010, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA (0x0010, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), SSL3_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA (0x0011, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA (0x0011, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), /** * @deprecated Replaced with TLS_DHE_DSS_WITH_DES_CBC_SHA. */ @Deprecated SSL3_DHE_DSS_WITH_DES_CBC_SHA (0x0012, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1 }), TLS_DHE_DSS_WITH_DES_CBC_SHA (0x0012, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1 }), /** * @deprecated Replaced with TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA. */ @Deprecated SSL3_DHE_DSS_WITH_3DES_EDE_CBC_SHA (0x0013, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA (0x0013, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), SSL3_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA (0x0014, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA (0x0014, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), /** * @deprecated Replaced with TLS_DHE_RSA_WITH_DES_CBC_SHA. */ @Deprecated SSL3_DHE_RSA_WITH_DES_CBC_SHA (0x0015, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1 }), TLS_DHE_RSA_WITH_DES_CBC_SHA (0x0015, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1 }), /** * @deprecated Replaced with TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA. */ @Deprecated SSL3_DHE_RSA_WITH_3DES_EDE_CBC_SHA (0x0016, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA (0x0016, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), SSL3_DH_ANON_EXPORT_WITH_RC4_40_MD5 (0x0017, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 (0x0017, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), /** * @deprecated Replaced with TLS_DH_anon_WITH_RC4_128_MD5. */ @Deprecated SSL3_DH_ANON_WITH_RC4_128_MD5 (0x0018, SSLVersion.SSL_3_0), TLS_DH_anon_WITH_RC4_128_MD5 (0x0018, SSLVersion.SSL_3_0), SSL3_DH_ANON_EXPORT_WITH_DES40_CBC_SHA (0x0019, SSLVersion.SSL_3_0), TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA (0x0019, SSLVersion.SSL_3_0), /** * @deprecated Replaced with TLS_DH_anon_WITH_DES_CBC_SHA. */ @Deprecated SSL3_DH_ANON_WITH_DES_CBC_SHA (0x001a, SSLVersion.SSL_3_0), TLS_DH_anon_WITH_DES_CBC_SHA (0x001a, SSLVersion.SSL_3_0), /** * @deprecated Replaced with TLS_DH_anon_WITH_3DES_EDE_CBC_SHA. */ @Deprecated SSL3_DH_ANON_WITH_3DES_EDE_CBC_SHA (0x001b, SSLVersion.SSL_3_0), TLS_DH_anon_WITH_3DES_EDE_CBC_SHA (0x001b, SSLVersion.SSL_3_0), /** * @deprecated As of NSS 3.11, FORTEZZA is no longer supported. */ @Deprecated SSL3_FORTEZZA_DMS_WITH_NULL_SHA (0x001c, SSLVersion.SSL_3_0), /** * @deprecated As of NSS 3.11, FORTEZZA is no longer supported. */ @Deprecated SSL3_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA (0x001d, SSLVersion.SSL_3_0), /** * @deprecated As of NSS 3.11, FORTEZZA is no longer supported. */ @Deprecated SSL3_FORTEZZA_DMS_WITH_RC4_128_SHA (0x001e, SSLVersion.SSL_3_0), SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA (0xfeff, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), SSL_RSA_FIPS_WITH_DES_CBC_SHA (0xfefe, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA (0x0062, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), TLS_RSA_EXPORT1024_WITH_RC4_56_SHA (0x0064, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA (0x0063, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA (0x0065, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), TLS_DHE_DSS_WITH_RC4_128_SHA (0x0066, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1 }), TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 (0x0067, new SSLVersion[] { SSLVersion.TLS_1_2 }), TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 (0x006A, new SSLVersion[] { SSLVersion.TLS_1_2 }), TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 (0x006B, new SSLVersion[] { SSLVersion.TLS_1_2 }), // New TLS cipher suites in NSS 3.4 TLS_RSA_WITH_AES_128_CBC_SHA (0x002F, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DH_DSS_WITH_AES_128_CBC_SHA (0x0030, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DH_RSA_WITH_AES_128_CBC_SHA (0x0031, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DHE_DSS_WITH_AES_128_CBC_SHA (0x0032, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), /** * @deprecated Replaced with TLS_DH_anon_WITH_AES_128_CBC_SHA. */ @Deprecated TLS_DH_ANON_WITH_AES_128_CBC_SHA (0x0034, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1 }), TLS_DH_anon_WITH_AES_128_CBC_SHA (0x0034, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1 }), TLS_RSA_WITH_AES_256_CBC_SHA (0x0035, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DH_DSS_WITH_AES_256_CBC_SHA (0x0036, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DH_RSA_WITH_AES_256_CBC_SHA (0x0037, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DHE_DSS_WITH_AES_256_CBC_SHA (0x0038, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), /** * @deprecated Replaced with TLS_DH_anon_WITH_AES_256_CBC_SHA. */ @Deprecated TLS_DH_ANON_WITH_AES_256_CBC_SHA (0x003A, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DH_anon_WITH_AES_256_CBC_SHA (0x003A, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_RSA_WITH_NULL_SHA256 (0x003B, new SSLVersion[] { SSLVersion.TLS_1_2 }), TLS_RSA_WITH_AES_128_CBC_SHA256 (0x003C, new SSLVersion[] { SSLVersion.TLS_1_2 }), TLS_RSA_WITH_AES_256_CBC_SHA256 (0x003D, new SSLVersion[] { SSLVersion.TLS_1_2 }), TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 (0x0041, new SSLVersion[] { SSLVersion.TLS_1_2 }), TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (0x0041, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA (0x0042, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA (0x0043, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA (0x0044, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA (0x0045, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), /** * @deprecated Replaced with TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA. */ @Deprecated TLS_DH_ANON_WITH_CAMELLIA_128_CBC_SHA (0x0046, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA (0x0046, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (0x0084, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA (0x0085, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA (0x0086, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA (0x0087, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA (0x0088, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), /** * @deprecated Replaced with TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA. */ @Deprecated TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA (0x0089, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA (0x0089, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_RSA_WITH_SEED_CBC_SHA (0x0096, new SSLVersion[] { SSLVersion.SSL_3_0, SSLVersion.TLS_1_0 }), TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009C, SSLVersion.TLS_1_2), TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009D, SSLVersion.TLS_1_2), TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x009E, SSLVersion.TLS_1_2), TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x009F, SSLVersion.TLS_1_2), TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 (0x00A2, SSLVersion.TLS_1_2), TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 (0x00A3, SSLVersion.TLS_1_2), TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 (0x00AA, SSLVersion.TLS_1_2), TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 (0x00AB, SSLVersion.TLS_1_2), TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00FF), TLS_FALLBACK_SCSV (0x5600), TLS_ECDH_ECDSA_WITH_NULL_SHA (0xc001, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDH_ECDSA_WITH_RC4_128_SHA (0xc002, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA (0xc003, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1 }), TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA (0xc004, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA (0xc005, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDHE_ECDSA_WITH_NULL_SHA (0xc006, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDHE_ECDSA_WITH_RC4_128_SHA (0xc007, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA (0xc008, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1 }), TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDH_RSA_WITH_NULL_SHA (0xc00b, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDH_RSA_WITH_RC4_128_SHA (0xc00c, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA (0xc00d, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDH_RSA_WITH_AES_128_CBC_SHA (0xc00e, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDH_RSA_WITH_AES_256_CBC_SHA (0xc00f, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDHE_RSA_WITH_NULL_SHA (0xc010, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDHE_RSA_WITH_RC4_128_SHA (0xc011, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA (0xc012, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDH_anon_WITH_NULL_SHA (0xc015, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDH_anon_WITH_RC4_128_SHA (0xc016, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA (0xc017, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDH_anon_WITH_AES_128_CBC_SHA (0xc018, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDH_anon_WITH_AES_256_CBC_SHA (0xc019, true, new SSLVersion[] { SSLVersion.TLS_1_0, SSLVersion.TLS_1_1, SSLVersion.TLS_1_2 }), TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (0xc023, true, SSLVersion.TLS_1_2), TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (0xc024, true, SSLVersion.TLS_1_2), TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027, true, SSLVersion.TLS_1_2), TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028, true, SSLVersion.TLS_1_2), TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02B, true, SSLVersion.TLS_1_2), TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02C, true, SSLVersion.TLS_1_2), TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02D, true, SSLVersion.TLS_1_2), TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02F, true, SSLVersion.TLS_1_2), TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030, true, SSLVersion.TLS_1_2), TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 (0xc031, true, SSLVersion.TLS_1_2), /* * TLS 1.3 */ /* draft-ietf-tls-chacha20-poly1305-04 */ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xCCA8, true, SSLVersion.TLS_1_2), TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xCCA9, true, SSLVersion.TLS_1_2), TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xCCAA, SSLVersion.TLS_1_2), TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 (0xCCAC, true, SSLVersion.TLS_1_2), TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 (0xCCAD, SSLVersion.TLS_1_2), TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 (0xD001, true, SSLVersion.TLS_1_2), TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384 (0xD002, true, SSLVersion.TLS_1_2), /* Special TLS 1.3 cipher suites that really just specify AEAD */ TLS_AES_128_GCM_SHA256 (0x1301, false, SSLVersion.TLS_1_3), TLS_AES_256_GCM_SHA384 (0x1302, false, SSLVersion.TLS_1_3), TLS_CHACHA20_POLY1305_SHA256 (0x1303, false, SSLVersion.TLS_1_3); private int id; private boolean ecc; private SSLVersion[] versions; private boolean supported; private SSLCipher(int id) { /* Should only be used with TLS_EMPTY_RENEGOTIATION_INFO_SCSV and * TLS_FALLBACK_SCSV. */ this(id, false, (SSLVersion[]) null); } private SSLCipher(int id, SSLVersion version) { this(id, false, new SSLVersion[] { version }); } private SSLCipher(int id, SSLVersion[] versions) { this(id, false, versions); } private SSLCipher(int id, boolean ecc, SSLVersion version) { this(id, ecc, new SSLVersion[] { version }); } private SSLCipher(int id, boolean ecc, SSLVersion[] versions) { this.id = id; this.ecc = ecc; this.versions = versions; this.supported = checkSupportedStatus(id); } private static native boolean checkSupportedStatus(int id); public int getID() { return id; } public boolean isECC() { return ecc; } public boolean supportsTLSVersion(SSLVersion v) { if (versions == null) { return false; } for (SSLVersion version : versions) { if (version == v) { return true; } } return false; } public boolean isTLSv12() { return supportsTLSVersion(SSLVersion.TLS_1_2); } public boolean isTLSv13() { return supportsTLSVersion(SSLVersion.TLS_1_3); } public boolean isSupported() { return supported; } public boolean requiresRSACert() { return this.name().contains("_RSA_") && !this.name().contains("ECDH_RSA"); } public boolean requiresECDSACert() { return this.name().contains("_ECDSA_") || this.name().contains("ECDH_RSA"); } public boolean requiresDSSCert() { return this.name().contains("_DSS_"); } public static SSLCipher valueOf(int id) { for (SSLCipher cipher : SSLCipher.class.getEnumConstants()) { if (cipher.id == id) return cipher; } return null; } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLCipherAlgorithm.java000066400000000000000000000013701412550063600251160ustar00rootroot00000000000000package org.mozilla.jss.ssl; public enum SSLCipherAlgorithm { ssl_calg_null (0), ssl_calg_rc4 (1), ssl_calg_rc2 (2), ssl_calg_des (3), ssl_calg_3des (4), ssl_calg_idea (5), ssl_calg_fortezza (6), ssl_calg_aes (7), ssl_calg_camellia (8), ssl_calg_seed (9), ssl_calg_aes_gcm (10), ssl_calg_chacha20 (11); private int value; private SSLCipherAlgorithm(int value) { this.value = value; } public int getValue() { return value; } public static SSLCipherAlgorithm valueOf(int value) { for (SSLCipherAlgorithm alg : SSLCipherAlgorithm.values()) { if (alg.value == value) { return alg; } } return null; } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLClient.java000066400000000000000000000355141412550063600232620ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // This demonstrates the SSL client-side support // package org.mozilla.jss.ssl; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.net.InetAddress; import java.net.Socket; import java.util.Hashtable; import org.mozilla.jss.CertDatabaseException; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.InitializationValues; import org.mozilla.jss.KeyDatabaseException; import org.mozilla.jss.crypto.AlreadyInitializedException; /** * Parameters supported by this socket test: * * filename file to be read from https server (default: /index.html) * port port to connect to (default: 443) * ipaddr address to connect to (overrides hostname, no default) * hostname host to connect to (no default) * clientauth do client-auth or not (default: no client-auth) * * The following parameters are used for regression testing, so * we can print success or failure of the test. * * filesize size of file to be read * status security status of connection - this has to be an integer * cipher * sessionKeySize * sessionSecretSize * issuer * subject * certSerialNum * */ public class SSLClient { boolean handshakeEventHappened = false; boolean doClientAuth = false; Hashtable args; PrintStream results; String versionStr; String argNames[] = { "filename", "port", "ipaddr", "hostname", "filesize", "status", "sessionKeySize", "sessionSecretSize", "cipher", "issuer", "subject", "certSerialNum", }; String values[] = { "/index", // filename "443", // port to connect to "", // ipaddr (use hostname instead) "trading.etrade.com", // hostname to connect to "1024", // filesize "2", // status, 2 means ??? "128", // expected session key size "128", // expected session key secret bits "RC48", // expected cipher "CN=Hardcore Certificate Server II, OU=Hardcore, O=Netscape Communications Corporation, C=US", // expected issuer DN of server "CN=hbombsgi.mcom.com, OU=Hardcore, C=US", // expected subject DN of server "00C3", // serial number }; String okay = "okay"; String failed = "FAILED"; private static String htmlHeader = "SSL Client Tester"; private static String htmlTail = "\n"; /* simple helper functions */ private boolean isInvalid(String s) { return (s == null) || s.equals(""); } private String getArgument(String key) { return args.get(key); } /* * return "okay" or "FAILED" based on equality of * the argument strings */ private String cmp(String s1, String s2) { return s1.equals(s2) ? okay : failed; } private String cmp(String s1, int s2) { return cmp(s1, Integer.toString(s2)); } public void run(boolean printHeader, boolean testRegression) { try { SSLHandshakeCompletedListener listener = null; if (printHeader) results.println(htmlHeader); results.println("SSL Client Tester"); results.println( "$Id$ " + versionStr); SSLSocket s; String hostname; int port; String filename = getArgument("filename"); if (isInvalid(filename)) { filename = "/index.html"; } String msg = "GET " + filename; String portstr = getArgument("port"); if (isInvalid(portstr)) { port = 443; } else { port = Integer.valueOf(portstr).intValue(); } String addrstr = getArgument("ipaddr"); hostname = addrstr; // unless it gets changed String tmpStr = getArgument("clientauth"); if (isInvalid(tmpStr)) doClientAuth = false; else { tmpStr = tmpStr.toLowerCase(); doClientAuth = !(tmpStr.equals("off") || tmpStr.equals("false") || tmpStr.equals("0")); } if (isInvalid(addrstr)) { // check for a host name hostname = getArgument("hostname"); if (isInvalid(hostname)) { throw new Exception("hostname not specified"); } } results.println("Connecting to " + hostname + " on port " + port); SSLCertificateApprovalCallback approvalCallback = new TestCertApprovalCallback(); SSLClientCertificateSelectionCallback certSelectionCallback = new TestClientCertificateSelectionCallback(); Socket js = new Socket(InetAddress.getByName(hostname), port); //s = new SSLSocket(hostname, port, null, 0, s = new SSLSocket(js, hostname, approvalCallback, certSelectionCallback); s.forceHandshake(); results.println("Connected."); // select the cert for client auth // You will have to provide a certificate with this // name if you expect client auth to work. //s.setClientCertNickname("JavaSSLTestClientCert"); // Setup a handshake callback. This listener will get invoked // When the SSL handshake is completed on this socket. listener = new ClientHandshakeCB(this); s.addHandshakeCompletedListener(listener); //s.forceHandshake(); OutputStream o = s.getOutputStream(); PrintOutputStreamWriter out = new PrintOutputStreamWriter(o); results.println("Sending: " + msg + " to " + hostname + ", " + port); // send HTTP GET message across SSL connection out.println(msg + "\r"); InputStream in = s.getInputStream(); byte[] bytes = new byte[4096]; int totalBytes = 0; int numReads = 0; String lastBytes = null; // now try to read data back from the SSL connection try { for (;;) { results.println("Calling Read."); int n = in.read(bytes, 0, bytes.length); if (n == -1) { results.println("EOF found."); break; } if (n == 0) { results.println("Zero bytes read?"); break; } numReads++; if (totalBytes == 0) { // don't print forever... String data = new String(bytes, 0, 30, "8859_1"); results.println("Read " + n + " bytes of data"); results.println("First 30 bytes: " + escapeHTML(data)); } totalBytes += n; lastBytes = new String(bytes, n - 31, 30, "8859_1"); } } catch (IOException e) { results.println( "IOException while reading from pipe? Actually got " + totalBytes + " bytes total"); e.printStackTrace(results); results.println(""); throw e; } finally { results.println("Last 30 bytes: " + lastBytes); results.println("Number of read() calls: " + numReads); /* * if you want to test sslimpl.c's nsn_ThrowError(), try * uncommenting the following line. This will cause the * getStatus() call to fail. */ // in.close(); results.println("Diagnostics"); String tmp; SSLSecurityStatus status = s.getStatus(); results.println("Total bytes read: " + totalBytes); results.println("Security status of session:"); results.println(status.toString()); // now, for the regression testing stuff if (testRegression) { results.println("Regression Tests"); results.println("Handshake callback event happened: " + ((handshakeEventHappened) ? okay : failed)); if (!isInvalid(tmp = getArgument("filesize"))) { results.println("filesize: " + cmp(tmp, totalBytes)); } if (!isInvalid(tmp = getArgument("status"))) { results.println("status: " + cmp(tmp, status.getSecurityStatus())); } if (!isInvalid(tmp = getArgument("sessionKeySize"))) { results.println("sessionKeySize: " + cmp(tmp, status.getSessionKeySize())); } if (!isInvalid(tmp = getArgument("sessionSecretSize"))) { results.println("sessionSecretSize: " + cmp(tmp, status.getSessionSecretSize())); } if (!isInvalid(tmp = getArgument("cipher"))) { results.println("cipher: " + cmp(tmp, status.getCipher())); } if (!isInvalid(tmp = getArgument("issuer"))) { results.println("issuer: " + cmp(tmp, status.getRemoteIssuer())); } if (!isInvalid(tmp = getArgument("subject"))) { results.println("subject: " + cmp(tmp, status.getRemoteSubject())); } if (!isInvalid(tmp = getArgument("certSerialNum"))) { String serialNum = status.getSerialNumber(); results.println("certSerialNum: " + cmp(tmp, serialNum)); } } // if false } // Got here, so no exception thrown above. // Try to clean up. o.close(); o = null; in.close(); in = null; if (listener != null) { s.removeHandshakeCompletedListener(listener); listener = null; } s.close(); s = null; } catch (Exception e) { results.println("***** TEST FAILED *****"); e.printStackTrace(results); results.println("If there is no stack trace, try disabling the JIT and trying again."); } results.println("END OF TEST"); } /** * given an input string, convert less-than, greater-than, and ampersand * from raw characters to escaped characters * (< becomes `&lt;', etc.) */ private String escapeHTML(String s) { StringBuffer result = new StringBuffer(); // this is inefficient, but I don't care for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); switch (c) { case '<': result.append("<"); break; case '>': result.append(">"); break; case '&': result.append("&"); break; default: result.append(c); break; } } return result.toString(); } public SSLClient(PrintStream ps, String verStr, String[] argv) { this.args = new Hashtable<>(); this.results = ps; this.versionStr = verStr; for (int i = 0; i < argNames.length; i++) { String value = values[i]; if (value != null) this.args.put(argNames[i], value); } for (int i = 0; i < argv.length; i += 2) { this.args.put(argv[i], argv[i + 1]); } } static final int cipherSuites[] = { SSLSocket.SSL3_RSA_WITH_RC4_128_MD5, SSLSocket.SSL3_RSA_WITH_3DES_EDE_CBC_SHA, SSLSocket.SSL3_RSA_WITH_DES_CBC_SHA, SSLSocket.SSL3_RSA_EXPORT_WITH_RC4_40_MD5, SSLSocket.SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSLSocket.SSL3_RSA_WITH_NULL_MD5, 0 }; public static void main(String argv[]) throws Exception { int i; try { InitializationValues vals = new InitializationValues("."); CryptoManager.initialize(vals); // NSSInit.initialize("secmod.db", "key3.db", "cert7.db"); } catch (KeyDatabaseException kdbe) { System.out.println("Couldn't open the key database"); return; } catch (CertDatabaseException cdbe) { System.out.println("Couldn't open the certificate database"); return; } catch (AlreadyInitializedException aie) { System.out.println("CryptoManager already initialized???"); return; } catch (Exception e) { System.out.println("Exception occurred: " + e.getMessage()); return; } /* enable all the SSL2 cipher suites */ for (i = SSLSocket.SSL2_RC4_128_WITH_MD5; i <= SSLSocket.SSL2_DES_192_EDE3_CBC_WITH_MD5; ++i) { // SSLSocket.setPermittedByPolicy(i, SSLSocket.SSL_ALLOWED); if (i != 0xFF05) { SSLSocket.setCipherPreferenceDefault(i, true); } } /* enable all the SSL3 cipher suites */ for (i = 0; cipherSuites[i] != 0; ++i) { // SSLSocket.setPermittedByPolicy(cipherSuites[i], SSLSocket.SSL_ALLOWED); SSLSocket.setCipherPreferenceDefault(cipherSuites[i], true); } SSLClient x = new SSLClient(System.out, "Stand alone Ver 0.01", argv); x.run(true, false); } } class ClientHandshakeCB implements SSLHandshakeCompletedListener { SSLClient sc; ClientHandshakeCB(SSLClient sc) { this.sc = sc; } @Override public void handshakeCompleted(SSLHandshakeCompletedEvent event) { try { sc.handshakeEventHappened = true; SSLSecurityStatus status = event.getStatus(); sc.results.println("handshake happened\n" + status); System.out.println("Cert is " + status.getPeerCertificate()); } catch (Exception e) { e.printStackTrace(); } } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLClientCertificateSelectionCallback.java000066400000000000000000000024501412550063600307010ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * SSLSecurityStatus.java * * */ package org.mozilla.jss.ssl; import java.util.Vector; /** * Implement this if you want to specify dynamically which certificate * should be presented for client authentication. */ public interface SSLClientCertificateSelectionCallback { /** * This method will be called from the native callback code * when a certificate is requested. You must return a String * which is the nickname of the certificate you wish to present. * * @param nicknames A Vector of Strings. These strings are * an aid to the user to select the correct nickname. This list is * made from the list of all certs which are valid, match the * CA's trusted by the server, and which you have the private * key of. If nicknames.length is 0, you should present an * error to the user saying 'you do not have any unexpired * certificates'. * @return You must return the nickname of the certificate you * wish to use. You can return null if you do not wish to send * a certificate. */ public String select(Vector nicknames); } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLCompressionMethod.java000066400000000000000000000010111412550063600254670ustar00rootroot00000000000000package org.mozilla.jss.ssl; public enum SSLCompressionMethod { NULL (0), DEFLATE (1); private int value; private SSLCompressionMethod(int value) { this.value = value; } public int getValue() { return value; } public static SSLCompressionMethod valueOf(int value) { for (SSLCompressionMethod method : SSLCompressionMethod.values()) { if (method.value == value) { return method; } } return null; } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLHandshakeCompletedEvent.java000066400000000000000000000020741412550063600265640ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * SSLHandshakeCompletedEvent.java * * */ package org.mozilla.jss.ssl; import java.net.*; import java.util.*; /* * right now, this only extends EventObject, but it will eventually * extend javax.net.ssl.HandshakeCompletedEvent */ /** * This class represents the event telling you a handshake * operation is complete. */ public class SSLHandshakeCompletedEvent extends EventObject { private static final long serialVersionUID = 1L; public SSLHandshakeCompletedEvent(SSLSocket socket) { super(socket); } /** * get security information about this socket, including * cert data */ public SSLSecurityStatus getStatus() throws SocketException { return getSocket().getStatus(); } /** * get socket on which the event occured */ public SSLSocket getSocket() { return (SSLSocket)getSource(); } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLHandshakeCompletedListener.java000066400000000000000000000010471412550063600272670ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* * SSLHandshakeCompletedListener.java * * */ package org.mozilla.jss.ssl; import java.util.*; /** * This interface is used when you want to know that a security * handshake is complete. */ public interface SSLHandshakeCompletedListener extends EventListener { public void handshakeCompleted(SSLHandshakeCompletedEvent event); } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLInputStream.java000066400000000000000000000030351412550063600243100ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.ssl; import java.io.IOException; class SSLInputStream extends java.io.InputStream { SSLInputStream(SSLSocket sock) { this.sock = sock; } @Override public int available() throws IOException { return sock.socketAvailable(); } @Override public void close() throws IOException { sock.close(); } @Override public int read() throws IOException { byte[] b = new byte[1]; int nread = read(b, 0, 1); if (nread == -1) { return nread; } else { return (b[0]) & (0xff); } } @Override public int read(byte[] b) throws IOException { return read(b, 0, b.length); } @Override public int read(byte[] b, int off, int len) throws IOException { return sock.read(b, off, len); } @Override public long skip(long n) throws IOException { long numSkipped = 0; int size = (int) (n < 2048 ? n : 2048); byte[] trash = new byte[size]; while (n > 0) { size = (int) (n < 2048 ? n : 2048); int nread = read(trash, 0, size); if (nread <= 0) { break; } numSkipped += nread; n -= nread; } return numSkipped; } private SSLSocket sock; } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLKEAType.java000066400000000000000000000011561412550063600233010ustar00rootroot00000000000000package org.mozilla.jss.ssl; public enum SSLKEAType { ssl_kea_null (0), ssl_kea_rsa (1), ssl_kea_dh (2), ssl_kea_fortezza (3), ssl_kea_ecdh (4), ssl_kea_ecdh_psk (5), ssl_kea_dh_psk (6), ssl_kea_tls13_any (7); private int value; private SSLKEAType(int value) { this.value = value; } public int getValue() { return value; } public static SSLKEAType valueOf(int value) { for (SSLKEAType type : SSLKEAType.values()) { if (type.value == value) { return type; } } return null; } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLMACAlgorithm.java000066400000000000000000000011741412550063600243060ustar00rootroot00000000000000package org.mozilla.jss.ssl; public enum SSLMACAlgorithm { ssl_mac_null (0), ssl_mac_md5 (1), ssl_mac_sha (2), ssl_hmac_md5 (3), ssl_hmac_sha (4), ssl_hmac_sha256 (5), ssl_mac_aead (6), ssl_hmac_sha384 (7); private int value; private SSLMACAlgorithm(int value) { this.value = value; } public int getValue() { return value; } public static SSLMACAlgorithm valueOf(int value) { for (SSLMACAlgorithm alg : SSLMACAlgorithm.values()) { if (alg.value == value) { return alg; } } return null; } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLNamedGroup.java000066400000000000000000000036401412550063600241000ustar00rootroot00000000000000package org.mozilla.jss.ssl; import org.mozilla.jss.util.ECCurve; public enum SSLNamedGroup { ssl_grp_ec_sect163k1(1), ssl_grp_ec_sect163r1(2), ssl_grp_ec_sect163r2(3), ssl_grp_ec_sect193r1(4), ssl_grp_ec_sect193r2(5), ssl_grp_ec_sect233k1(6), ssl_grp_ec_sect233r1(7), ssl_grp_ec_sect239k1(8), ssl_grp_ec_sect283k1(9), ssl_grp_ec_sect283r1(10), ssl_grp_ec_sect409k1(11), ssl_grp_ec_sect409r1(12), ssl_grp_ec_sect571k1(13), ssl_grp_ec_sect571r1(14), ssl_grp_ec_secp160k1(15), ssl_grp_ec_secp160r1(16), ssl_grp_ec_secp160r2(17), ssl_grp_ec_secp192k1(18), ssl_grp_ec_secp192r1(19), ssl_grp_ec_secp224k1(20), ssl_grp_ec_secp224r1(21), ssl_grp_ec_secp256k1(22), ssl_grp_ec_secp256r1(23, ECCurve.P256), ssl_grp_ec_secp384r1(24, ECCurve.P384), ssl_grp_ec_secp521r1(25, ECCurve.P521), ssl_grp_ec_curve25519(29), ssl_grp_ffdhe_2048(256), ssl_grp_ffdhe_3072(257), ssl_grp_ffdhe_4096(258), ssl_grp_ffdhe_6144(259), ssl_grp_ffdhe_8192(260), ssl_grp_none(65537), ssl_grp_ffdhe_custom(65538); private int value; private ECCurve curve; private SSLNamedGroup(int value) { this(value, null); } private SSLNamedGroup(int value, ECCurve curve) { this.curve = curve; this.value = value; } public int getValue() { return value; } public ECCurve getCurve() { return curve; } public static SSLNamedGroup valueOf(int value) { for (SSLNamedGroup group : SSLNamedGroup.values()) { if (group.value == value) { return group; } } return null; } public static SSLNamedGroup valueOf(ECCurve curve) { for (SSLNamedGroup group : SSLNamedGroup.values()) { if (group.curve == curve) { return group; } } return null; } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLOutputStream.java000066400000000000000000000015271412550063600245150ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.ssl; import java.io.IOException; class SSLOutputStream extends java.io.OutputStream { SSLOutputStream(SSLSocket sock) { this.sock = sock; } @Override public void write(int b) throws IOException { write(new byte[] { (byte) b }, 0, 1); } @Override public void write(byte[] b) throws IOException { write(b, 0, b.length); } @Override public void write(byte[] b, int off, int len) throws IOException { sock.write(b, off, len); } @Override public void close() throws IOException { sock.close(); } private SSLSocket sock; } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLProtocolVariant.java000066400000000000000000000011731412550063600251640ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.ssl; public class SSLProtocolVariant { public static final SSLProtocolVariant STREAM = new SSLProtocolVariant(SocketBase.SSL_Variant_Stream); public static final SSLProtocolVariant DATA_GRAM = new SSLProtocolVariant(SocketBase.SSL_Variant_Datagram); private int _enum; private SSLProtocolVariant(int val) { _enum = val; } public int getEnum() { return _enum; } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLSecurityStatus.java000066400000000000000000000110401412550063600250430ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.ssl; import org.mozilla.jss.crypto.X509Certificate; /** * This class represents the known state of an SSL connection: what cipher * is being used, how secure it is, and who's on the other end. */ public class SSLSecurityStatus { int status; String cipher; int sessionKeySize; int sessionSecretSize; String issuer; String subject; String serialNumber; X509Certificate certificate; // Certificate may be null if client does not present certificate final public int STATUS_NOOPT = -1; final public int STATUS_OFF = 0; final public int STATUS_ON_HIGH = 1; final public int STATUS_ON_LOW = 2; /** * @deprecated As of NSS 3.11, FORTEZZA is no longer supported. * STATUS_FORTEZZA is a placeholder for backward compatibility. */ @Deprecated final public int STATUS_FORTEZZA = 3; /** * This constructor is called from the native SSL code * It's not necessary for you to call this. */ public SSLSecurityStatus(int status, String cipher, int sessionKeySize, int sessionSecretSize, String issuer, String subject, String serialNumber, X509Certificate certificate) { String noCert = "no certificate"; this.status = status; this.cipher = cipher; this.sessionKeySize = sessionKeySize; this.sessionSecretSize = sessionSecretSize; this.certificate = certificate; if (noCert.equals(issuer)) this.issuer = null; else this.issuer = issuer; if (noCert.equals(subject)) this.subject = null; else this.subject = subject; this.serialNumber = serialNumber; } /** * Query if security is enabled on this socket. */ public boolean isSecurityOn() { return status > 0; } /** * Get exact security status of socket. */ public int getSecurityStatus() { return status; } /** * Query which cipher is being used in this session. */ public String getCipher() { return cipher; } /** * Query how many bits long the session key is. More bits are better. */ public int getSessionKeySize() { return sessionKeySize; } /** * To satisfy export restrictions, some of the session key may * be revealed. This function tells you how many bits are * actually secret. */ public int getSessionSecretSize() { return sessionSecretSize; } /** * Get the distinguished name of the remote certificate's issuer */ public String getRemoteIssuer() { return issuer; } /** * Get the distinguished name of the subject of the remote certificate */ public String getRemoteSubject() { return subject; } /** * Get the serial number of the remote certificate */ public String getSerialNumber() { return serialNumber; } /** * Retrieve certificate presented by the other other end * of the socket *

* Not Supported in NSS 2.0 Beta release. *

* Can be null if peer did not present a certificate. */ public X509Certificate getPeerCertificate() { return certificate; } /** * Get a pretty string to show to a user, summarizing the contents * of this object */ @Override public String toString() { String statusString; switch (status) { case STATUS_NOOPT: statusString = "NOOPT"; break; case STATUS_OFF: statusString = "OFF"; break; case STATUS_ON_HIGH: statusString = "ON HIGH"; break; case STATUS_ON_LOW: statusString = "ON LOW"; break; case STATUS_FORTEZZA: statusString = "FORTEZZA"; break; default: statusString = "unknown"; break; } return "Status: " + statusString + "\n" + "Cipher: " + cipher + "\n" + "Session key size: " + sessionKeySize + "\n" + "Session secret size: " + sessionSecretSize + "\n" + "Issuer: " + issuer + "\n" + "Subject: " + subject + "\n" + "Serial number: " + serialNumber + "\n"; } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLServer.java000066400000000000000000000230561412550063600233100ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // This program demonstrates SSL server-side support. It expects // (HTTP) clients to connect to it, and will respond to HTTP // GET requests // // tabstops: 4 package org.mozilla.jss.ssl; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.util.Hashtable; import org.mozilla.jss.CertDatabaseException; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.KeyDatabaseException; /** * Parameters supported by this socket test: * * filename file to be read from https server (default: /index.html) * port port to connect to (default: 443) * clientauth do client-auth or not (default: no client-auth) * * The following parameters are used for regression testing, so * we can print success or failure of the test. * * filesize size of file to be read * status security status of connection - this has to be an integer * */ public class SSLServer { boolean handshakeEventHappened = false; boolean doClientAuth = false; Hashtable args; PrintStream results; String versionStr; String argNames[] = { "filename", "port", "filesize", "clientauth", "nickname" }; String values[] = { "data1k.txt", // filename "2000", // port "1024", // filesize "false", // request client auth "SSLServer" // nickname of cert to use }; private static String htmlHeader = "SSL Server Tester"; private static String htmlTail = "\n"; /* simple helper functions */ private boolean isInvalid(String s) { return (s == null) || s.equals(""); } private String getArgument(String key) { return args.get(key); } String okay = "okay"; String failed = "FAILED"; public void run() { try { SSLServerSocket l; SSLSocket s; int port; String tmpStr; String portStr; String nickname; results.println(htmlHeader); portStr = getArgument("port"); if (isInvalid(portStr)) { port = 443; } else { port = Integer.valueOf(portStr).intValue(); } results.println("here"); tmpStr = getArgument("clientauth"); if (!isInvalid(tmpStr)) { tmpStr = tmpStr.toLowerCase(); doClientAuth = !(tmpStr.equals("off") || tmpStr.equals("false") || tmpStr.equals("0")); } l = new SSLServerSocket(port); results.println("Listening " + l.toString()); // select the server's cert/key nickname = getArgument("nickname"); results.println("Getting Cert:" + nickname + ""); l.setServerCertNickname(nickname); if (doClientAuth) { l.requestClientAuth(true); } // wait for and accept a connection. s = (SSLSocket) l.accept(); results.println("Accepted."); handleConnection(s); // handleConnection will close s, as appropriate. s = null; l.close(); l = null; } catch (Exception e) { results.println("***** TEST FAILED *****"); e.printStackTrace(results); results.println( "If there is no stack trace, try disabling the JIT and trying again."); } results.println("END OF TEST"); } public void handleConnection(SSLSocket s) throws Exception { SSLHandshakeCompletedListener listener = null; listener = new ServerHandshakeCB(this); s.addHandshakeCompletedListener(listener); results.println("Connected to " + s.toString()); InputStream in = s.getInputStream(); byte[] bytes = new byte[4096]; int totalBytes = 0; int numReads = 0; // now try to read data from the SSL connection try { boolean endFound = false; while (!endFound && totalBytes < bytes.length) { results.println("Calling Read."); int n = in.read(bytes, totalBytes, bytes.length - totalBytes); if (n == -1) { results.println("EOF found."); break; } if (n == 0) { results.println("Zero bytes read?"); break; } numReads++; results.println("Read " + n + " bytes of data"); totalBytes += n; for (int i = 0; i + 3 < bytes.length; ++i) { if (bytes[i] == 0x0D && bytes[i + 1] == 0x0A && bytes[i + 2] == 0x0D && bytes[i + 3] == 0x0A) { results.println("Empty line found."); endFound = true; break; } } } } catch (IOException e) { results.println( "IOException while reading from pipe? Actually got " + totalBytes + " bytes total"); e.printStackTrace(results); results.println(""); throw e; } results.println("Number of read() calls: " + numReads); results.println("Total bytes read: " + totalBytes); String msg = null; if (totalBytes > 0) { msg = new String(bytes, 0, totalBytes, "8859_1"); results.println("Request received:"); results.println(msg); results.println(""); } SSLSecurityStatus status = s.getStatus(); results.println("Security status of session:"); results.println(status.toString()); results.println("Handshake callback event happened: " + ((handshakeEventHappened) ? okay : failed)); OutputStream os = s.getOutputStream(); PrintOutputStreamWriter out = new PrintOutputStreamWriter(os); os = null; // don't keep this reference lying around String reply = "HTTP/1.0 200 OK\r\n" + "Server: Netscape-Enterprise/2.0a\r\n" + "Date: Tue, 01 Apr 1998 22:10:05 GMT\r\n" + "Content-type: text/plain\r\n" + "\r\n" + msg; out.println(reply); // Got here, so no exception thrown above. // Try to clean up. in.close(); in = null; if (listener != null) { s.removeHandshakeCompletedListener(listener); listener = null; } out.close(); out = null; s.close(); s = null; } public SSLServer(PrintStream ps, String verStr) { this.args = new Hashtable<>(); this.results = ps; this.versionStr = verStr; for (int i = 0; i < argNames.length; i++) { String value = values[i]; if (value != null) this.args.put(argNames[i], value); } } static final int cipherSuites[] = { SSLSocket.SSL3_RSA_WITH_RC4_128_MD5, SSLSocket.SSL3_RSA_WITH_3DES_EDE_CBC_SHA, SSLSocket.SSL3_RSA_WITH_DES_CBC_SHA, SSLSocket.SSL3_RSA_EXPORT_WITH_RC4_40_MD5, SSLSocket.SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5, SSLSocket.SSL3_RSA_WITH_NULL_MD5, 0 }; public static void main(String[] argv) throws Exception { int i; System.out.println("SSLServer started\n"); try { CryptoManager.initialize("."); } catch (KeyDatabaseException kdbe) { System.out.println("Couldn't open the key database\n"); return; } catch (CertDatabaseException cdbe) { System.out.println("Couldn't open the certificate database"); return; } catch (org.mozilla.jss.crypto.AlreadyInitializedException aie) { System.out.println("CryptoManager already initialized???"); return; } catch (java.security.GeneralSecurityException e) { System.out.println("General security exception while initializing"); return; } SSLServerSocket.configServerSessionIDCache(10, 0, 0, null); /* enable all the SSL2 cipher suites */ for (i = SSLSocket.SSL2_RC4_128_WITH_MD5; i <= SSLSocket.SSL2_DES_192_EDE3_CBC_WITH_MD5; ++i) { // SSLSocket.setPermittedByPolicy(i, SSLSocket.SSL_ALLOWED); SSLSocket.setCipherPreferenceDefault(i, true); } /* enable all the SSL3 cipher suites */ for (i = 0; cipherSuites[i] != 0; ++i) { // SSLSocket.setPermittedByPolicy(cipherSuites[i], SSLSocket.SSL_ALLOWED); SSLSocket.setCipherPreferenceDefault(cipherSuites[i], true); } SSLServer x = new SSLServer(System.out, "Stand alone Ver 0.01"); x.run(); } } class ServerHandshakeCB implements SSLHandshakeCompletedListener { SSLServer sc; ServerHandshakeCB(SSLServer sc) { this.sc = sc; } @Override public void handshakeCompleted(SSLHandshakeCompletedEvent event) { sc.handshakeEventHappened = true; sc.results.println("handshake happened"); } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLServerSocket.c000066400000000000000000000211441412550063600237560ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include #include #include "jssl.h" #ifdef WINNT #include #endif JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLServerSocket_socketListen (JNIEnv *env, jobject self, jint backlog) { JSSL_SocketData *sock; if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) goto finish; if( PR_Listen(sock->fd, backlog) != PR_SUCCESS ) { JSSL_throwSSLSocketException(env, "Failed to set listen backlog on socket"); goto finish; } finish: return; } JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_ssl_SSLServerSocket_socketAccept (JNIEnv *env, jobject self, jobject newSock, jint timeout, jboolean handshakeAsClient) { JSSL_SocketData *sock; PRNetAddr addr; PRFileDesc *newFD=NULL; PRIntervalTime ivtimeout; JSSL_SocketData *newSD=NULL; jbyteArray sdArray = NULL; SECStatus status; PRThread *me; if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) goto finish; ivtimeout = (timeout > 0) ? PR_MillisecondsToInterval(timeout) : PR_INTERVAL_NO_TIMEOUT; if( handshakeAsClient ) { status = SSL_OptionSet(sock->fd, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE); if( status != SECSuccess ) { JSSL_throwSSLSocketException(env, "Failed to set option to handshake as client"); goto finish; } } /* Set the current thread doing the accept. */ me = PR_GetCurrentThread(); PR_Lock(sock->lock); if ( sock->closePending ) { PR_Unlock(sock->lock); JSSL_throwSSLSocketException(env, "Accept operation failed: socket is closing"); goto finish; } PR_ASSERT(sock->accepter == NULL); sock->accepter = me; PR_Unlock(sock->lock); newFD = PR_Accept(sock->fd, &addr, ivtimeout); PR_Lock(sock->lock); PR_ASSERT(sock->accepter == me); sock->accepter = NULL; PR_Unlock(sock->lock); if( newFD == NULL ) { PRErrorCode err = PR_GetError(); if( err == PR_PENDING_INTERRUPT_ERROR ) { #ifdef WINNT /* Clean up after PR_interrupt. */ PR_NT_CancelIo(sock->fd); #endif JSSL_throwSSLSocketException(env, "Accept operation interrupted"); } else if( err == PR_IO_TIMEOUT_ERROR ) { #ifdef WINNT PR_NT_CancelIo(sock->fd); #endif JSSL_throwSSLSocketException(env, "Accept operation timed out"); } else if( err == PR_IO_ERROR ) { JSSL_throwSSLSocketException(env, "Accept operation received IO error"); } else { JSSL_throwSSLSocketException(env, "Accept operation failed"); } goto finish; } newSD = JSSL_CreateSocketData(env, newSock, newFD, NULL /* priv */); if( newSD == NULL ) { goto finish; } newFD = NULL; /* setup the handshake callback */ status = SSL_HandshakeCallback(newSD->fd, JSSL_HandshakeCallback, newSD); if( status != SECSuccess ) { JSSL_throwSSLSocketException(env, "Unable to install handshake callback"); goto finish; } /* pass the pointer back to Java */ sdArray = JSS_ptrToByteArray(env, (void*) newSD); if( sdArray == NULL ) { /* exception was thrown */ goto finish; } finish: if( (*env)->ExceptionOccurred(env) != NULL ) { if( newSD != NULL ) { JSSL_DestroySocketData(env, newSD); } if( newFD != NULL ) { PR_Close(newFD); } } return sdArray; } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLServerSocket_abortAccept( JNIEnv *env, jobject self) { JSSL_SocketData *sock = NULL; if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) goto finish; /* * The java layer prevents I/O once close has been * called but if an accept is in progress then abort it. * For WINNT the accept method must check for * PR_PENDING_INTERRUPT_ERROR and call PR_NT_CancelIo. */ PR_Lock(sock->lock); if ( sock->accepter ) { PR_Interrupt(sock->accepter); } sock->closePending = PR_TRUE; /* socket is to be closed */ PR_Unlock(sock->lock); finish: EXCEPTION_CHECK(env, sock) return; } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLServerSocket_clearSessionCache( JNIEnv *env, jclass clazz) { SSL_ClearSessionCache(); } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLServerSocket_configServerSessionIDCache( JNIEnv *env, jclass myClass, jint maxEntries, jint ssl2Timeout, jint ssl3Timeout, jstring nameString) { const char* dirName = NULL; SECStatus status; dirName = JSS_RefJString(env, nameString); status = SSL_ConfigServerSessionIDCache( maxEntries, ssl2Timeout, ssl3Timeout, dirName); if (status != SECSuccess) { JSSL_throwSSLSocketException(env, "Failed to configure server session ID cache"); goto finish; } finish: JSS_DerefJString(env, nameString, dirName); } /* * This is here for backwards binary compatibility: I didn't want to remove * the symbol from the DLL. This would only get called if someone were using * a pre-3.2 version of the JSS classes with this post-3.2 library. Using * different versions of the classes and the C code is not supported. */ JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLServerSocket_setServerCertNickname( JNIEnv *env, jobject self, jstring nick) { PR_ASSERT(0); JSS_throwMsg(env, SOCKET_EXCEPTION, "JSS JAR/DLL version mismatch"); } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLServerSocket_setServerCert( JNIEnv *env, jobject self, jobject certObj) { JSSL_SocketData *sock; CERTCertificate* cert=NULL; PK11SlotInfo* slot=NULL; SECKEYPrivateKey* privKey=NULL; SECStatus status; if( certObj == NULL ) { JSS_throw(env, NULL_POINTER_EXCEPTION); goto finish; } if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) goto finish; if( JSS_PK11_getCertPtr(env, certObj, &cert) != PR_SUCCESS ) { goto finish; } PR_ASSERT(cert!=NULL); /* shouldn't happen */ if( JSS_PK11_getCertSlotPtr(env, certObj, &slot) != PR_SUCCESS ) { goto finish; } PR_ASSERT(slot!=NULL); /* shouldn't happen */ privKey = PK11_FindPrivateKeyFromCert(slot, cert, NULL); if (privKey != NULL) { status = SSL_ConfigServerCert(sock->fd, cert, privKey, NULL, 0); if( status != SECSuccess) { JSSL_throwSSLSocketException(env, "Failed to configure secure server certificate and key"); goto finish; } } else { JSSL_throwSSLSocketException(env, "Failed to locate private key"); goto finish; } finish: if(privKey!=NULL) { SECKEY_DestroyPrivateKey(privKey); } } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLServerSocket_setReuseAddress( JNIEnv *env, jobject self, jboolean reuse) { JSSL_SocketData *sock; PRStatus status; PRSocketOptionData sockOptData; if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) goto finish; sockOptData.option = PR_SockOpt_Reuseaddr; sockOptData.value.reuse_addr = ((reuse == JNI_TRUE) ? PR_TRUE : PR_FALSE ); status = PR_SetSocketOption(sock->fd, &sockOptData); if( status != PR_SUCCESS ) { JSSL_throwSSLSocketException(env, "PR_SetSocketOption failed"); goto finish; } finish: return; } JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_ssl_SSLServerSocket_getReuseAddress( JNIEnv *env, jobject self) { JSSL_SocketData *sock; PRStatus status; PRSocketOptionData sockOptData; if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) goto finish; sockOptData.option = PR_SockOpt_Reuseaddr; status = PR_GetSocketOption(sock->fd, &sockOptData); if( status != PR_SUCCESS ) { JSSL_throwSSLSocketException(env, "PR_SetSocketOption failed"); goto finish; } finish: /* If we got here via failure, reuse_addr might be uninitialized. But in * that case we're throwing an exception, so the return value doesn't * matter. */ return ((sockOptData.value.reuse_addr == PR_TRUE) ? JNI_TRUE : JNI_FALSE); } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLServerSocket.java000066400000000000000000000513651412550063600244650ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.ssl; import java.io.IOException; import java.net.InetAddress; import java.net.Socket; import java.net.SocketException; import java.net.SocketTimeoutException; import javax.net.ssl.SSLException; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.crypto.ObjectNotFoundException; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.ssl.javax.JSSEngine; /** * SSL server socket. */ public class SSLServerSocket extends java.net.ServerSocket { /* * Locking rules of SSLServerSocket * * isClosed and inAccept must be accessed with the object locked. * * acceptLock must be locked throughout the accept method. It is * used to serialize accept calls on the object. */ private SocketProxy sockProxy = null; private boolean handshakeAsClient = false; private SocketBase base = new SocketBase(); private boolean isClosed = false; private boolean inAccept = false; private java.lang.Object acceptLock = new java.lang.Object(); /** * The default size of the listen queue. */ public static final int DEFAULT_BACKLOG = 50; /** * Creates a server socket listening on the given port. * The listen queue will be of size DEFAULT_BACKLOG. */ public SSLServerSocket(int port) throws IOException { this(port, DEFAULT_BACKLOG, null); } /** * Creates a server socket listening on the given port. * * @param backlog The size of the socket's listen queue. */ public SSLServerSocket(int port, int backlog) throws IOException { this(port, backlog, null); } /** * Creates a server socket listening on the given port. * * @param backlog The size of the socket's listen queue. * @param bindAddr The local address to which to bind. If null, an * unspecified local address will be bound to. */ public SSLServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException { this(port, backlog, bindAddr, null); } /** * Creates a server socket listening on the given port. * * @param backlog The size of the socket's listen queue. * @param bindAddr The local address to which to bind. If null, an * unspecified local address will be bound to. * @param certApprovalCallback Will get called to approve any certificate * presented by the client. */ public SSLServerSocket(int port, int backlog, InetAddress bindAddr, SSLCertificateApprovalCallback certApprovalCallback) throws IOException { this(port, backlog, bindAddr, certApprovalCallback, false); } /** * Creates a server socket listening on the given port. * * @param backlog The size of the socket's listen queue. * @param bindAddr The local address to which to bind. If null, an * unspecified local address will be bound to. * @param certApprovalCallback Will get called to approve any certificate * presented by the client. * @param reuseAddr Reuse the local bind port; this parameter sets * the SO_REUSEADDR option on the socket before calling * bind(). The default is false for backward * compatibility. */ public SSLServerSocket(int port, int backlog, InetAddress bindAddr, SSLCertificateApprovalCallback certApprovalCallback, boolean reuseAddr) throws IOException { // Dance the dance of fools. The superclass doesn't have a default // constructor, so we have to trick it here. This is an example // of WHY WE SHOULDN'T BE EXTENDING SERVERSOCKET. super(0); super.close(); // create the socket int socketFamily = SocketBase.SSL_AF_INET; if (SocketBase.supportsIPV6()) { socketFamily = SocketBase.SSL_AF_INET6; } sockProxy = new SocketProxy( base.socketCreate(this, certApprovalCallback, null, socketFamily)); base.setProxy(sockProxy); setReuseAddress(reuseAddr); byte[] bindAddrBA = null; if (bindAddr != null) { bindAddrBA = bindAddr.getAddress(); } base.socketBind(bindAddrBA, port); String hostName = null; if (bindAddr != null) { hostName = bindAddr.getCanonicalHostName(); } socketListen(backlog); } private native void socketListen(int backlog) throws SocketException; /** * Accepts a connection. This call will block until a connection is made * or the timeout is reached. * * @return java.net.Socket Local socket for client communication * * @throws IOException If an input or output exception occurred * @throws SocketTimeoutException If the socket times out trying to connect * @throws SSLSocketException JSS subclass of java.net.SocketException */ @Override public Socket accept() throws IOException { synchronized (acceptLock) { synchronized (this) { if (isClosed) { throw new IOException( "SSLServerSocket has been closed, and cannot be reused."); } inAccept = true; } SSLSocket s = new SSLSocket(); try { /* * socketAccept can throw an exception for timeouts, * IO errors, or PR_Interrupt called by abortAccept. * So first get a socket pointer, and if successful * create the SocketProxy. */ byte[] socketPointer = null; socketPointer = socketAccept(s, base.getTimeout(), handshakeAsClient); SocketProxy sp = new SocketProxy(socketPointer); s.setSockProxy(sp); } finally { synchronized (this) { inAccept = false; } } return s; } } /** * Sets the SO_TIMEOUT socket option. * * @param timeout The timeout time in milliseconds. */ @Override public void setSoTimeout(int timeout) { base.setTimeout(timeout); } /** * Returns the current value of the SO_TIMEOUT socket option. * * @return The timeout time in milliseconds. */ @Override public int getSoTimeout() { return base.getTimeout(); } @Override public native void setReuseAddress(boolean reuse) throws SocketException; @Override public native boolean getReuseAddress() throws SocketException; private native void abortAccept() throws SocketException; private native byte[] socketAccept(SSLSocket s, int timeout, boolean handshakeAsClient) throws SocketException, SocketTimeoutException; /** * Empties the SSL client session ID cache. */ public static native void clearSessionCache(); /** * @deprecated finalize() in Object has been deprecated */ @Override @Deprecated protected void finalize() throws Throwable { close(); /* in case user never called close */ } /** * @return The local port. */ @Override public int getLocalPort() { return base.getLocalPort(); } /** * Closes this socket. */ @Override public void close() throws IOException { synchronized (this) { if (isClosed) { /* finalize calls close or user calls close more than once */ return; } isClosed = true; if (sockProxy == null) { /* nothing to do */ return; } if (inAccept) { abortAccept(); } } /* Lock acceptLock to ensure that accept has been aborted. */ synchronized (acceptLock) { base.close(); sockProxy = null; base.setProxy(null); } } // This directory is used as the default for the Session ID cache private final static String UNIX_TEMP_DIR = "/tmp"; private final static String WINDOWS_TEMP_DIR = "\\temp"; /** * Configures the session ID cache. * * @param maxSidEntries The maximum number of entries in the cache. If * 0 is passed, the default of 10,000 is used. * @param ssl2EntryTimeout The lifetime in seconds of an SSL2 session. * The minimum timeout value is 5 seconds and the maximum is 24 hours. * Values outside this range are replaced by the server default value * of 100 seconds. * @param ssl3EntryTimeout The lifetime in seconds of an SSL3 session. * The minimum timeout value is 5 seconds and the maximum is 24 hours. * Values outside this range are replaced by the server default value * of 100 seconds. * @param cacheFileDirectory The pathname of the directory that * will contain the session cache. If null is passed, the server default * is used: /tmp on Unix and \\temp on Windows. */ public static void configServerSessionIDCache(int maxSidEntries, int ssl2EntryTimeout, int ssl3EntryTimeout, String cacheFileDirectory) throws SocketException { try { JSSEngine.initializeSessionCache(maxSidEntries, ssl3EntryTimeout, cacheFileDirectory); } catch (SSLException parent) { // Because JSSEngine.initializeSessionCache is utilized in // javax's SSLEngine implementations, it can only throw a // SSLException. However, in the event it fails, we should // re-throw it here as a SocketException, keeping the signature // the same. SocketException se = new SSLSocketException(parent.getMessage()); se.addSuppressed(parent); throw se; } } /** * Sets the certificate to use for server authentication. */ public void setServerCertNickname(String nick) throws SocketException { try { setServerCert(CryptoManager.getInstance().findCertByNickname(nick)); } catch (NotInitializedException nie) { throw new SocketException("CryptoManager not initialized: " + nie); } catch (ObjectNotFoundException onfe) { throw new SocketException("Object not found: " + onfe); } catch (TokenException te) { throw new SocketException("Token Exception: " + te); } } /** * Sets the certificate to use for server authentication. */ public native void setServerCert( org.mozilla.jss.crypto.X509Certificate certnickname) throws SocketException; /** * Enables/disables the request of client authentication. This is only * meaningful for the server end of the SSL connection. During the next * handshake, the remote peer will be asked to authenticate itself. * * @see org.mozilla.jss.ssl.SSLServerSocket#requireClientAuth */ public void requestClientAuth(boolean b) throws SocketException { base.requestClientAuth(b); } /** * @deprecated As of JSS 3.0. This method is misnamed. Use * requestClientAuth instead. */ @Deprecated public void setNeedClientAuth(boolean b) throws SocketException { base.requestClientAuth(b); } /** * Enables/disables the request of client authentication. This is only * meaningful for the server end of the SSL connection. During the next * handshake, the remote peer will be asked to authenticate itself. *

* In addition, the client certificate's expiration will not * prevent it from being accepted. * * @see org.mozilla.jss.ssl.SSLServerSocket#requireClientAuth * public void requestClientAuthNoExpiryCheck(boolean b) * throws SocketException * { * base.requestClientAuthNoExpiryCheck(b); * } * * /** * @deprecated As of JSS 3.0. This method is misnamed. Use * requestClientAuthNoExpiryCheck instead. */ @Deprecated public void setNeedClientAuthNoExpiryCheck(boolean b) throws SocketException { base.requestClientAuthNoExpiryCheck(b); } /** * Enables SSL v2 on this socket. It is enabled by default, unless the * default has been changed with SSLSocket.enableSSL2Default. */ public void enableSSL2(boolean enable) throws SocketException { base.enableSSL2(enable); } /** * Enables SSL v3 on this socket. It is enabled by default, unless the * default has been changed with SSLSocket.enableSSL3Default. */ public void enableSSL3(boolean enable) throws SocketException { base.enableSSL3(enable); } /** * Enables TLS on this socket. It is enabled by default, unless the * default has been changed with SSLSocket.enableTLSDefault. */ public void enableTLS(boolean enable) throws SocketException { base.enableTLS(enable); } /** * Enables Session tickets on this socket. It is disabled by default, * unless the default has been changed with * SSLSocket.enableSessionTicketsDefault. */ public void enableSessionTickets(boolean enable) throws SocketException { base.enableSessionTickets(enable); } /** * Enables the mode of renegotiation that the peer must use. * The default is never renegotiate at all unless the default * has been changed with SSLSocket.enableRenegotiationDefault. * * @param mode One of: * SSLSocket.SSL_RENEGOTIATE_NEVER - Never renegotiate at all. * * SSLSocket.SSL_RENEGOTIATE_UNRESTRICTED - Renegotiate without * restriction, whether or not the peer's hello bears the TLS * renegotiation info extension. Vulnerable, as in the past. * * SSLSocket.SSL_RENEGOTIATE_REQUIRES_XTN - Only renegotiate if the * peer's hello bears the TLS renegotiation_info extension. This is * safe renegotiation. * * SSLSocket.SSL_RENEGOTIATE_TRANSITIONAL - Disallow unsafe * renegotiation in server sockets only, but allow clients * to continue to renegotiate with vulnerable servers. * This value should only be used during the transition period * when few servers have been upgraded. */ public void enableRenegotiation(int mode) throws SocketException { if (mode >= SocketBase.SSL_RENEGOTIATE_NEVER && mode <= SocketBase.SSL_RENEGOTIATE_TRANSITIONAL) { base.enableRenegotiation(mode); } else { throw new SocketException("Incorrect input value."); } } /** * For this socket require that the peer must send * Signaling Cipher Suite Value (SCSV) or Renegotiation Info (RI) * extension in ALL handshakes. It is disabled by default, * unless the default has been changed with * SSLSocket.enableRequireSafeNegotiationDefault. */ public void enableRequireSafeNegotiation(boolean enable) throws SocketException { base.enableRequireSafeNegotiation(enable); } /** * Enable rollback detection for this socket. * It is enabled by default, unless the default has been changed * with SSLSocket.enableRollbackDetectionDefault. */ public void enableRollbackDetection(boolean enable) throws SocketException { base.enableRollbackDetection(enable); } /** * This option, enableStepDown, is concerned with the generation * of step-down keys which are used with export suites. * If the server cert's public key is 512 bits or less, * this option is ignored because step-down keys don't * need to be generated. * If the server cert's public key is more than 512 bits, * this option has the following effect: * enable=true: generate step-down keys * enable=false: don't generate step-down keys; disable * export cipher suites * * This option is enabled by default; unless the default has * been changed with SSLSocket.enableStepDownDefault. */ public void enableStepDown(boolean enable) throws SocketException { base.enableStepDown(enable); } /** * Enable simultaneous read/write by separate read and write threads * (full duplex) for this socket. * It is disabled by default, unless the default has been changed * with SSLSocket.enableFDXDefault. */ public void enableFDX(boolean enable) throws SocketException { base.enableFDX(enable); } /** * Enable sending v3 client hello in v2 format for this socket. * It is enabled by default, unless the default has been changed * with SSLSocket.enableV2CompatibleHelloDefault. */ public void enableV2CompatibleHello(boolean enable) throws SocketException { base.enableV2CompatibleHello(enable); } /** * @return a String listing the current SSLOptions for this socket. */ public String getSSLOptions() { return base.getSSLOptions(); } /** * @return the local address of this server socket. */ @Override public InetAddress getInetAddress() { return base.getLocalAddress(); } /** * Sets whether the socket requires client authentication from the remote * peer. If requestClientAuth() has not already been called, this * method will tell the socket to request client auth as well as requiring * it. * * @deprecated use requireClientAuth(int) */ @Deprecated public void requireClientAuth(boolean require, boolean onRedo) throws SocketException { base.requireClientAuth(require, onRedo); } /** * Sets whether the socket requires client authentication from the remote * peer. If requestClientAuth() has not already been called, this * method will tell the socket to request client auth as well as requiring * it. * * @param mode One of: SSLSocket.SSL_REQUIRE_NEVER, * SSLSocket.SSL_REQUIRE_ALWAYS, * SSLSocket.SSL_REQUIRE_FIRST_HANDSHAKE, * SSLSocket.SSL_REQUIRE_NO_ERROR */ public void requireClientAuth(int mode) throws SocketException { if (mode >= SocketBase.SSL_REQUIRE_NEVER && mode <= SocketBase.SSL_REQUIRE_NO_ERROR) { base.requireClientAuth(mode); } else { throw new SocketException("Incorrect input value."); } } /** * Sets the nickname of the certificate to use for client authentication. */ public void setClientCertNickname(String nick) throws SocketException { base.setClientCertNickname(nick); } /** * Sets the certificate to use for client authentication. */ public void setClientCert(org.mozilla.jss.crypto.X509Certificate cert) throws SocketException { base.setClientCert(cert); } /** * Determines whether this end of the socket is the client or the server * for purposes of the SSL protocol. By default, it is the server. * * @param b true if this end of the socket is the SSL slient, false * if it is the SSL server. */ public void setUseClientMode(boolean b) { handshakeAsClient = b; } /** * Enables/disables the session cache. By default, the session cache * is enabled. */ public void useCache(boolean b) throws SocketException { base.useCache(b); } /** * Returns the addresses and ports of this socket * or an error message if the socket is not in a valid state. */ @Override public String toString() { try { InetAddress inetAddr = getInetAddress(); int localPort = getLocalPort(); StringBuffer buf = new StringBuffer(); buf.append("SSLServerSocket[addr="); buf.append(inetAddr); buf.append(",localport="); buf.append(localPort); buf.append("]"); return buf.toString(); } catch (Exception e) { return "Exception caught in toString(): " + e.getMessage(); } } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLSignatureScheme.java000066400000000000000000000024261412550063600251260ustar00rootroot00000000000000package org.mozilla.jss.ssl; public enum SSLSignatureScheme { ssl_sig_none (0), ssl_sig_rsa_pkcs1_sha1 (0x0201), ssl_sig_rsa_pkcs1_sha256 (0x0401), ssl_sig_rsa_pkcs1_sha384 (0x0501), ssl_sig_rsa_pkcs1_sha512 (0x0601), ssl_sig_ecdsa_secp256r1_sha256 (0x0403), ssl_sig_ecdsa_secp384r1_sha384 (0x0503), ssl_sig_ecdsa_secp521r1_sha512 (0x0603), ssl_sig_rsa_pss_rsae_sha256 (0x0804), ssl_sig_rsa_pss_rsae_sha384 (0x0805), ssl_sig_rsa_pss_rsae_sha512 (0x0806), ssl_sig_ed25519 (0x0807), ssl_sig_ed448 (0x0808), ssl_sig_rsa_pss_pss_sha256 (0x0809), ssl_sig_rsa_pss_pss_sha384 (0x080a), ssl_sig_rsa_pss_pss_sha512 (0x080b), ssl_sig_dsa_sha1 (0x0202), ssl_sig_dsa_sha256 (0x0402), ssl_sig_dsa_sha384 (0x0502), ssl_sig_dsa_sha512 (0x0602), ssl_sig_ecdsa_sha1 (0x0203), ssl_sig_rsa_pkcs1_sha1md5 (0x10101); private int value; private SSLSignatureScheme(int value) { this.value = value; } public int getValue() { return value; } public static SSLSignatureScheme valueOf(int value) { for (SSLSignatureScheme scheme : SSLSignatureScheme.values()) { if (scheme.value == value) { return scheme; } } return null; } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLSocket.c000066400000000000000000001022031412550063600225630ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include #include "_jni/org_mozilla_jss_ssl_SSLSocket.h" #include "jssl.h" #include #ifdef WINNT #include #define AF_INET6 23 #endif #ifdef WIN32 #include #define AF_INET6 23 #endif #include "SSLVersionRange.h" /* * support TLS v1.1, v1.2, and v1.3 * returns SSL version range bound by the version range provided by the system. * Doesn't change the defaults. */ JNIEXPORT jobject JNICALL Java_org_mozilla_jss_ssl_SSLSocket_boundSSLVersionRange(JNIEnv *env, jclass clazz, jint ssl_variant, jint min, jint max) { SECStatus status; SSLVersionRange vrange; SSLVersionRange supported_range; jobject versionRange = NULL; if (ssl_variant <0 || ssl_variant >= JSSL_enums_size|| min <0 || min >= JSSL_enums_size || max <0 || max >= JSSL_enums_size) { char buf[128]; PR_snprintf(buf, 128, "JSS checkSSLVersionRangeDefault(): for variant=%d min=%d max=%d failed - out of range for array JSSL_enums size: %d", JSSL_enums[ssl_variant], min, max, JSSL_enums_size); JSSL_throwSSLSocketException(env, buf); goto finish; } vrange.min = JSSL_enums[min]; vrange.max = JSSL_enums[max]; /* get supported range */ status = SSL_VersionRangeGetSupported(JSSL_enums[ssl_variant], &supported_range); if( status != SECSuccess ) { char buf[128]; PR_snprintf(buf, 128, "SSL_VersionRangeGetSupported() for variant=%d failed: %d", JSSL_enums[ssl_variant], PR_GetError()); JSSL_throwSSLSocketException(env, buf); goto finish; } /* bind the min and max */ supported_range.min = MAX(supported_range.min, vrange.min); supported_range.max = MIN(supported_range.max, vrange.max); /* wrap NSS's SSLVersionRange into a org.mozilla.jss.ssl.SSLVersionRange */ versionRange = JSS_SSL_wrapVersionRange(env, supported_range); finish: return versionRange; } /* * support TLS v1.1, v1.2, and v1.3 * sets default SSL version range for sockets created after this call */ JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLSocket_setSSLVersionRangeDefault(JNIEnv *env, jclass clazz, jint ssl_variant, jint min, jint max) { SECStatus status; SSLVersionRange vrange; SSLVersionRange supported_range; if (ssl_variant <0 || ssl_variant >= JSSL_enums_size|| min <0 || min >= JSSL_enums_size || max <0 || max >= JSSL_enums_size) { char buf[128]; PR_snprintf(buf, 128, "JSS setSSLVersionRangeDefault(): for variant=%d min=%d max=%d failed - out of range for array JSSL_enums size: %d", JSSL_enums[ssl_variant], min, max, JSSL_enums_size); JSSL_throwSSLSocketException(env, buf); goto finish; } vrange.min = JSSL_enums[min]; vrange.max = JSSL_enums[max]; /* get supported range */ status = SSL_VersionRangeGetSupported(JSSL_enums[ssl_variant], &supported_range); if( status != SECSuccess ) { char buf[128]; PR_snprintf(buf, 128, "SSL_VersionRangeGetSupported() for variant=%d failed: %d", JSSL_enums[ssl_variant], PR_GetError()); JSSL_throwSSLSocketException(env, buf); goto finish; } /* now check the min and max */ if (vrange.min < supported_range.min || vrange.max > supported_range.max) { char buf[128]; PR_snprintf(buf, 128, "JSS setSSLVersionRangeDefault() for variant=%d with min=%d max=%d out of range (%d:%d): %d", JSSL_enums[ssl_variant], vrange.min, vrange.max, supported_range.min, supported_range.max, PR_GetError()); JSSL_throwSSLSocketException(env, buf); goto finish; } /* set the default SSL Version Range */ status = SSL_VersionRangeSetDefault(JSSL_enums[ssl_variant], &vrange); if( status != SECSuccess ) { char buf[128]; PR_snprintf(buf, 128, "SSL_VersionRangeSetDefault() for variant=%d with min=%d max=%d failed: %d", JSSL_enums[ssl_variant], vrange.min, vrange.max, PR_GetError()); JSSL_throwSSLSocketException(env, buf); goto finish; } finish: return; } /* * support TLS v1.1, v1.2, and v1.3 * sets SSL version range for this socket */ JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SocketBase_setSSLVersionRange (JNIEnv *env, jobject self, jint min, jint max) { SECStatus status; JSSL_SocketData *sock = NULL; SSLVersionRange vrange; if ( min <0 || min >= JSSL_enums_size || max <0 || max >= JSSL_enums_size) { char buf[128]; PR_snprintf(buf, 128, "JSS setSSLVersionRange(): for max=%d failed - out of range for array JSSL_enums size: %d", min, max, JSSL_enums_size); JSSL_throwSSLSocketException(env, buf); goto finish; } /* get my fd */ if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL ) { goto finish; } vrange.min = JSSL_enums[min]; vrange.max = JSSL_enums[max]; /* * set the SSL Version Range * The validity of the range will be checked by this NSS call */ status = SSL_VersionRangeSet(sock->fd, &vrange); if( status != SECSuccess ) { JSSL_throwSSLSocketException(env, "SSL_VersionRangeSet failed"); goto finish; } finish: EXCEPTION_CHECK(env, sock) return; } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLSocket_setSSLDefaultOption(JNIEnv *env, jclass clazz, jint joption, jint on) { SECStatus status; /* set the option */ status = SSL_OptionSetDefault(JSSL_enums[joption], on); if( status != SECSuccess ) { JSSL_throwSSLSocketException(env, "SSL_OptionSet failed"); goto finish; } finish: return; } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLSocket_setSSLDefaultOptionMode(JNIEnv *env, jclass clazz, jint joption, jint mode) { SECStatus status; /* set the option */ status = SSL_OptionSetDefault(JSSL_enums[joption], JSSL_enums[mode]); if( status != SECSuccess ) { JSSL_throwSSLSocketException(env, "SSL_OptionSet failed"); goto finish; } finish: return; } JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_ssl_SSLSocket_isFipsCipherSuiteNative(JNIEnv *env, jobject self, jint suite) { SECStatus status; PRBool bOption = PR_FALSE; SSLCipherSuiteInfo info; status = SSL_GetCipherSuiteInfo(suite, &info, sizeof info); if( status != SECSuccess ) { JSSL_throwSSLSocketException(env, "ciphersuite invalid"); } if (info.isFIPS == 1) bOption = PR_TRUE; return bOption; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_ssl_SSLSocket_getSSLDefaultOption(JNIEnv *env, jobject self, jint joption) { SECStatus status; PRBool bOption; /* get the Default option */ status = SSL_OptionGetDefault(JSSL_enums[joption], &bOption); if( status != SECSuccess ) { JSSL_throwSSLSocketException(env, "SSL_OptionGetDefault failed"); } return bOption; } #if 0 #define EXCEPTION_CHECK(env, sock) \ if( sock != NULL && sock->jsockPriv!=NULL) { \ JSS_SSL_processExceptions(env, sock->jsockPriv); \ } #endif JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLSocket_forceHandshake(JNIEnv *env, jobject self) { JSSL_SocketData *sock = NULL; int rv; /* get my fd */ if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) goto finish; /* do the work */ rv = SSL_ForceHandshake(sock->fd); if( rv != SECSuccess ) { JSSL_throwSSLSocketException(env, "SSL_ForceHandshake failed"); goto finish; } finish: EXCEPTION_CHECK(env, sock) return; } /* * linger * The linger time, in seconds. */ JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLSocket_setSoLinger(JNIEnv *env, jobject self, jboolean on, jint linger) { PRSocketOptionData sockOptions; PRStatus status; JSSL_SocketData *sock = NULL; if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL ) { goto finish; } sockOptions.option = PR_SockOpt_Linger; sockOptions.value.linger.polarity = on; if(on) { sockOptions.value.linger.linger = PR_SecondsToInterval(linger); } status = PR_SetSocketOption(sock->fd, &sockOptions); if( status != PR_SUCCESS ) { JSSL_throwSSLSocketException(env, "PR_SetSocketOption failed"); goto finish; } finish: EXCEPTION_CHECK(env, sock) return; } JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_ssl_SSLSocket_getTcpNoDelay(JNIEnv *env, jobject self) { PRSocketOptionData sockOptions; JSSL_SocketData *sock = NULL; PRStatus status; if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL ) { goto finish; } sockOptions.option = PR_SockOpt_NoDelay; status = PR_GetSocketOption(sock->fd, &sockOptions); if( status != PR_SUCCESS ) { JSSL_throwSSLSocketException(env, "PR_GetSocketOption failed"); goto finish; } finish: EXCEPTION_CHECK(env, sock) return sockOptions.value.no_delay; } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLSocket_setTcpNoDelay(JNIEnv *env, jobject self, jboolean on) { PRSocketOptionData sockOptions; PRStatus status; JSSL_SocketData *sock = NULL; if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) { goto finish; } sockOptions.option = PR_SockOpt_NoDelay; sockOptions.value.no_delay = on; status = PR_SetSocketOption(sock->fd, &sockOptions); if( status != PR_SUCCESS ) { JSSL_throwSSLSocketException(env, "PR_SetSocketOption failed"); goto finish; } finish: EXCEPTION_CHECK(env, sock) return; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_ssl_SSLSocket_getSendBufferSize(JNIEnv *env, jobject self) { PRSocketOptionData sockOptions; JSSL_SocketData *sock = NULL; PRStatus status; if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) { goto finish; } sockOptions.option = PR_SockOpt_SendBufferSize; status = PR_GetSocketOption(sock->fd, &sockOptions); if( status != PR_SUCCESS ) { JSSL_throwSSLSocketException(env, "PR_GetSocketOption failed"); goto finish; } finish: EXCEPTION_CHECK(env, sock) return sockOptions.value.send_buffer_size; } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLSocket_setSendBufferSize(JNIEnv *env, jobject self, jint size) { PRSocketOptionData sockOptions; PRStatus status; JSSL_SocketData *sock = NULL; if( JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) { goto finish; } sockOptions.option = PR_SockOpt_SendBufferSize; sockOptions.value.send_buffer_size = size; status = PR_SetSocketOption(sock->fd, &sockOptions); if( status != PR_SUCCESS ) { JSSL_throwSSLSocketException(env, "PR_SetSocketOption failed"); goto finish; } finish: EXCEPTION_CHECK(env, sock) return; } JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_ssl_SSLSocket_getKeepAlive(JNIEnv *env, jobject self) { PRSocketOptionData sockOptions; JSSL_SocketData *sock = NULL; PRStatus status; if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) { goto finish; } sockOptions.option = PR_SockOpt_Keepalive; status = PR_GetSocketOption(sock->fd, &sockOptions); if( status != PR_SUCCESS ) { JSSL_throwSSLSocketException(env, "PR_GetSocketOption failed"); goto finish; } finish: EXCEPTION_CHECK(env, sock) return sockOptions.value.keep_alive; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_ssl_SSLSocket_getReceiveBufferSize( JNIEnv *env, jobject self) { PRSocketOptionData sockOptions; JSSL_SocketData *sock = NULL; PRStatus status; if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) { goto finish; } sockOptions.option = PR_SockOpt_RecvBufferSize; status = PR_GetSocketOption(sock->fd, &sockOptions); if( status != PR_SUCCESS ) { JSSL_throwSSLSocketException(env, "PR_GetSocketOption failed"); goto finish; } finish: EXCEPTION_CHECK(env, sock) return sockOptions.value.recv_buffer_size; } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLSocket_setReceiveBufferSize( JNIEnv *env, jobject self, jint size) { PRSocketOptionData sockOptions; PRStatus status; JSSL_SocketData *sock = NULL; if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) { goto finish; } sockOptions.option = PR_SockOpt_RecvBufferSize; sockOptions.value.recv_buffer_size = size; status = PR_SetSocketOption(sock->fd, &sockOptions); if( status != PR_SUCCESS ) { JSSL_throwSSLSocketException(env, "PR_SetSocketOption failed"); goto finish; } finish: EXCEPTION_CHECK(env, sock) return; } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLSocket_setKeepAlive(JNIEnv *env, jobject self, jboolean on) { PRSocketOptionData sockOptions; PRStatus status; JSSL_SocketData *sock = NULL; if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) { goto finish; } sockOptions.option = PR_SockOpt_Keepalive; sockOptions.value.keep_alive = on; status = PR_SetSocketOption(sock->fd, &sockOptions); if( status != PR_SUCCESS ) { JSSL_throwSSLSocketException(env, "PR_SetSocketOption failed"); goto finish; } finish: EXCEPTION_CHECK(env, sock) return; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_ssl_SSLSocket_getSoLinger(JNIEnv *env, jobject self) { PRSocketOptionData sockOptions; JSSL_SocketData *sock = NULL; jint retval=-1; PRStatus status; if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) { goto finish; } sockOptions.option = PR_SockOpt_Linger; status = PR_GetSocketOption(sock->fd, &sockOptions); if( status != PR_SUCCESS ) { JSSL_throwSSLSocketException(env, "PR_GetSocketOption failed"); goto finish; } if( sockOptions.value.linger.polarity == PR_TRUE ) { retval = PR_IntervalToSeconds(sockOptions.value.linger.linger); } else { retval = -1; } finish: EXCEPTION_CHECK(env, sock) return retval; } /* * This function is only here for binary compatibility. See * http://bugzilla.mozilla.org/show_bug.cgi?id=143254 */ JNIEXPORT jint JNICALL Java_org_mozilla_jss_ssl_SSLSocket_getLocalAddressNative(JNIEnv *env, jobject self) { PRNetAddr addr; if( JSSL_getSockAddr(env, self, &addr, LOCAL_SOCK) == PR_SUCCESS ) { return ntohl(addr.inet.ip); } else { return 0; } } JNIEXPORT jint JNICALL Java_org_mozilla_jss_ssl_SSLSocket_getPort(JNIEnv *env, jobject self) { PRNetAddr addr; if( JSSL_getSockAddr(env, self, &addr, PEER_SOCK) == PR_SUCCESS ) { return ntohs(addr.inet.port); } else { return 0; } } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLSocket_socketConnect (JNIEnv *env, jobject self, jbyteArray addrBA, jstring hostname, jint port) { JSSL_SocketData *sock; PRNetAddr addr; jbyte *addrBAelems = NULL; int addrBALen = 0; PRStatus status; int stat; const char *hostnameStr=NULL; jmethodID supportsIPV6ID; jclass socketBaseClass; jboolean supportsIPV6 = 0; if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) { /* exception was thrown */ goto finish; } /* * setup the PRNetAddr structure */ socketBaseClass = (*env)->FindClass(env, SOCKET_BASE_NAME); if( socketBaseClass == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } supportsIPV6ID = (*env)->GetStaticMethodID(env, socketBaseClass, SUPPORTS_IPV6_NAME, SUPPORTS_IPV6_SIG); if( supportsIPV6ID == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } supportsIPV6 = (*env)->CallStaticBooleanMethod(env, socketBaseClass, supportsIPV6ID); if (!JSS_RefByteArray(env, addrBA, &addrBAelems, &addrBALen)) { ASSERT_OUTOFMEM(env); goto finish; } /* * Tell SSL the URL we think we want to connect to. * This prevents man-in-the-middle attacks. */ hostnameStr = JSS_RefJString(env, hostname); if( hostnameStr == NULL ) goto finish; stat = SSL_SetURL(sock->fd, (char*)hostnameStr); if( stat != 0 ) { JSSL_throwSSLSocketException(env, "Failed to set the SSL URL"); goto finish; } if(addrBALen != 4 && addrBALen != 16) { JSSL_throwSSLSocketException(env, "Invalid address in connect!"); goto finish; } if( addrBALen == 4) { addr.inet.family = AF_INET; addr.inet.port = PR_htons(port); memcpy(&addr.inet.ip, addrBAelems, 4); if(supportsIPV6) { addr.ipv6.family = AF_INET6; addr.ipv6.port = PR_htons(port); PR_ConvertIPv4AddrToIPv6(addr.inet.ip,&addr.ipv6.ip); } } else { /* Must be 16 and ipv6 */ if(supportsIPV6) { addr.ipv6.family = AF_INET6; addr.ipv6.port = PR_htons(port); memcpy(&addr.ipv6.ip,addrBAelems, 16); } else { JSSL_throwSSLSocketException(env, "Invalid address in connect!"); goto finish; } } /* * make the connect call */ status = PR_Connect(sock->fd, &addr, PR_INTERVAL_NO_TIMEOUT); if( status != PR_SUCCESS) { JSSL_throwSSLSocketException(env, "Unable to connect"); goto finish; } finish: /* This method should never be called on a Java socket wrapper. */ PR_ASSERT( sock==NULL || sock->jsockPriv==NULL); JSS_DerefJString(env, hostname, hostnameStr); JSS_DerefByteArray(env, addrBA, addrBAelems, JNI_ABORT); } JNIEXPORT jobject JNICALL Java_org_mozilla_jss_ssl_SSLSocket_getStatus (JNIEnv *env, jobject self) { SECStatus secstatus; JSSL_SocketData *sock=NULL; int on; char *cipher=NULL; jobject cipherString; jint keySize; jint secretKeySize; char *issuer=NULL; jobject issuerString; char *subject=NULL; jobject subjectString; jobject statusObj = NULL; jclass statusClass; jmethodID statusCons; CERTCertificate *peerCert=NULL; jobject peerCertObj = NULL; char *serialNum = NULL; jobject serialNumObj = NULL; /* get the fd */ if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) { /* exception was thrown */ goto finish; } /* get the status */ secstatus = SSL_SecurityStatus( sock->fd, &on, &cipher, (int*)&keySize, (int*)&secretKeySize, &issuer, &subject); if(secstatus != SECSuccess) { JSSL_throwSSLSocketException(env, "Failed to retrieve socket security status"); goto finish; } /* * get the peer certificate */ peerCert = SSL_PeerCertificate(sock->fd); if( peerCert != NULL ) { /* the peer cert might be null, for example if this is the server * side and the client didn't auth. */ serialNum = CERT_Hexify(&peerCert->serialNumber, PR_FALSE /*do_colon*/); PR_ASSERT(serialNum != NULL); serialNumObj = (*env)->NewStringUTF(env, serialNum); if( serialNumObj == NULL ) { goto finish; } /* this call will wipe out peerCert */ peerCertObj = JSS_PK11_wrapCert(env, &peerCert); if( peerCertObj == NULL) { goto finish; } } /* * convert char*s to Java Strings */ cipherString = issuerString = subjectString = NULL; if( cipher != NULL ) cipherString = (*env)->NewStringUTF(env, cipher); if( issuer != NULL ) issuerString = (*env)->NewStringUTF(env, issuer); if( subject != NULL ) subjectString = (*env)->NewStringUTF(env, subject); /* * package the status into a new SSLSecurityStatus object */ statusClass = (*env)->FindClass(env, SSL_SECURITY_STATUS_CLASS_NAME); PR_ASSERT(statusClass != NULL); if( statusClass == NULL ) { /* exception was thrown */ goto finish; } statusCons = (*env)->GetMethodID(env, statusClass, SSL_SECURITY_STATUS_CONSTRUCTOR_NAME, SSL_SECURITY_STATUS_CONSTRUCTOR_SIG); PR_ASSERT(statusCons != NULL); if(statusCons == NULL ) { /* exception was thrown */ goto finish; } statusObj = (*env)->NewObject(env, statusClass, statusCons, on, cipherString, keySize, secretKeySize, issuerString, subjectString, serialNumObj, peerCertObj); finish: if( cipher != NULL ) { PR_Free(cipher); } if( issuer != NULL ) { PORT_Free(issuer); } if ( subject != NULL) { PORT_Free(subject); } if( peerCert != NULL ) { CERT_DestroyCertificate(peerCert); } if( serialNum != NULL ) { PR_Free(serialNum); } EXCEPTION_CHECK(env, sock) return statusObj; } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLSocket_setCipherPreference( JNIEnv *env, jobject sockObj, jint cipher, jboolean enable) { JSSL_SocketData *sock=NULL; SECStatus status; /* get the fd */ if (JSSL_getSockData(env, sockObj, &sock) != PR_SUCCESS || sock == NULL) { /* exception was thrown */ goto finish; } status = SSL_CipherPrefSet(sock->fd, cipher, enable); if( status != SECSuccess ) { char buf[128]; PR_snprintf(buf, 128, "Failed to %s cipher 0x%lx\n", (enable ? "enable" : "disable"), cipher); JSSL_throwSSLSocketException(env, buf); goto finish; } finish: EXCEPTION_CHECK(env, sock); } JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_ssl_SSLSocket_getCipherPreference( JNIEnv *env, jobject sockObj, jint cipher) { JSSL_SocketData *sock=NULL; SECStatus status; PRBool enabled = PR_FAILURE; /* get the fd */ if (JSSL_getSockData(env, sockObj, &sock) != PR_SUCCESS || sock == NULL) { /* exception was thrown */ goto finish; } status = SSL_CipherPrefGet(sock->fd, cipher, &enabled); if( status != SECSuccess ) { char buf[128]; PR_snprintf(buf, 128, "Failed to get preference for cipher 0x%lx\n", cipher); JSSL_throwSSLSocketException(env, buf); goto finish; } finish: EXCEPTION_CHECK(env, sock); return enabled; } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLSocket_setCipherPreferenceDefault( JNIEnv *env, jclass clazz, jint cipher, jboolean enable) { SECStatus status; /* set the preference */ status = SSL_CipherPrefSetDefault(cipher, enable); if(status != SECSuccess) { char buf[128]; PR_snprintf(buf, 128, "Failed to %s cipher 0x%lx\n", (enable ? "enable" : "disable"), cipher); JSSL_throwSSLSocketException(env, buf); goto finish; } finish: return; } JNIEXPORT jboolean JNICALL Java_org_mozilla_jss_ssl_SSLSocket_getCipherPreferenceDefault( JNIEnv *env, jclass clazz, jint cipher) { SECStatus status; PRBool enabled; /* get the preference */ status = SSL_CipherPrefGetDefault(cipher, &enabled); if(status != SECSuccess) { char buf[128]; PR_snprintf(buf, 128, "Failed to get default preference for " "cipher 0x%lx\n", cipher); JSSL_throwSSLSocketException(env, buf); goto finish; } finish: return enabled; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_ssl_SSLSocket_socketRead(JNIEnv *env, jobject self, jbyteArray bufBA, jint off, jint len, jint timeout) { JSSL_SocketData *sock = NULL; jbyte *buf = NULL; jint size; PRIntervalTime ivtimeout; PRThread *me; jint nread = -1; if (!JSS_RefByteArray(env, bufBA, &buf, &size)) { goto finish; } if (off < 0 || len < 0 || (off+len) > size) { JSS_throw(env, INDEX_OUT_OF_BOUNDS_EXCEPTION); goto finish; } ivtimeout = (timeout > 0) ? PR_MillisecondsToInterval(timeout) : PR_INTERVAL_NO_TIMEOUT; /* get the socket */ if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) { goto finish; } /* set the current thread doing the read */ me = PR_GetCurrentThread(); PR_Lock(sock->lock); if ( sock->closePending ) { PR_Unlock(sock->lock); JSSL_throwSSLSocketException(env, "Read operation interrupted"); goto finish; } PR_ASSERT(sock->reader == NULL); sock->reader = me; PR_Unlock(sock->lock); nread = PR_Recv(sock->fd, buf+off, len, 0 /*flags*/, ivtimeout); PR_Lock(sock->lock); PR_ASSERT(sock->reader == me); sock->reader = NULL; PR_Unlock(sock->lock); if( nread < 0 ) { PRErrorCode err = PR_GetError(); if( err == PR_PENDING_INTERRUPT_ERROR ) { #ifdef WINNT /* Clean up after PR_interrupt called by abortReadWrite. */ PR_NT_CancelIo(sock->fd); #endif JSSL_throwSSLSocketException(env, "Read operation interrupted"); } else if( err == PR_IO_TIMEOUT_ERROR ) { #ifdef WINNT /* * if timeout was set, and the PR_Recv timed out, * then cancel the I/O on the socket, otherwise PR_Recv() * will always return PR_IO_PENDING_ERROR on subsequent * calls */ PR_NT_CancelIo(sock->fd); #endif JSSL_throwSSLSocketException(env, "Operation timed out"); } else { JSSL_throwSSLSocketException(env, "Error reading from socket"); } goto finish; } if( nread == 0 ) { /* EOF in Java is -1 */ nread = -1; } finish: EXCEPTION_CHECK(env, sock) JSS_DerefByteArray(env, bufBA, buf, (nread>0) ? 0 /*copy and free*/ : JNI_ABORT /*free, no copy*/); return nread; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_ssl_SSLSocket_socketAvailable( JNIEnv *env, jobject self) { jint available=0; JSSL_SocketData *sock = NULL; if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) { goto finish; } available = SSL_DataPending(sock->fd); PR_ASSERT(available >= 0); finish: EXCEPTION_CHECK(env, sock) return available; } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLSocket_socketWrite(JNIEnv *env, jobject self, jbyteArray bufBA, jint off, jint len, jint timeout) { JSSL_SocketData *sock = NULL; jbyte *buf = NULL; jint size; PRIntervalTime ivtimeout; PRThread *me; PRInt32 numwrit; if (!JSS_RefByteArray(env, bufBA, &buf, &size)) { goto finish; } if (off < 0 || len < 0 || (off+len) > size) { JSS_throw(env, INDEX_OUT_OF_BOUNDS_EXCEPTION); goto finish; } ivtimeout = (timeout > 0) ? PR_MillisecondsToInterval(timeout) : PR_INTERVAL_NO_TIMEOUT; /* get the socket */ if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) { goto finish; } /* set the current thread doing the write */ me = PR_GetCurrentThread(); PR_Lock(sock->lock); if ( sock->closePending ) { PR_Unlock(sock->lock); JSSL_throwSSLSocketException(env, "Write operation interrupted"); goto finish; } PR_ASSERT(sock->writer == NULL); sock->writer = me; PR_Unlock(sock->lock); numwrit = PR_Send(sock->fd, buf+off, len, 0 /*flags*/, ivtimeout); PR_Lock(sock->lock); PR_ASSERT(sock->writer == me); sock->writer = NULL; PR_Unlock(sock->lock); if( numwrit < 0 ) { PRErrorCode err = PR_GetError(); if( err == PR_PENDING_INTERRUPT_ERROR ) { #ifdef WINNT /* clean up after PR_Interrupt called by abortReadWrite. */ PR_NT_CancelIo(sock->fd); #endif JSSL_throwSSLSocketException(env, "Write operation interrupted"); } else if( err == PR_IO_TIMEOUT_ERROR ) { #ifdef WINNT /* * if timeout was set, and the PR_Send() timed out, * then cancel the I/O on the socket, otherwise PR_Send() * will always return PR_IO_PENDING_ERROR on subsequent * calls */ PR_NT_CancelIo(sock->fd); #endif JSSL_throwSSLSocketException(env, "Operation timed out"); } else { JSSL_throwSSLSocketException(env, "Failed to write to socket"); } goto finish; } /* PR_Send is supposed to block until it sends everything */ PR_ASSERT(numwrit == len); finish: JSS_DerefByteArray(env, bufBA, buf, JNI_ABORT); EXCEPTION_CHECK(env, sock) } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLSocket_abortReadWrite( JNIEnv *env, jobject self) { JSSL_SocketData *sock = NULL; if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) goto finish; /* * The java layer prevents I/O once close has been * called but if an I/O operation is in progress then abort it. * For WINNT the read and write methods must check for the * PR_PENDING_INTERRUPT_ERROR and call PR_NT_CancelIo. */ PR_Lock(sock->lock); if ( sock->reader ) { PR_Interrupt(sock->reader); } if ( sock->writer ) { PR_Interrupt(sock->writer); } sock->closePending = PR_TRUE; /* socket is to be closed */ PR_Unlock(sock->lock); finish: EXCEPTION_CHECK(env, sock) return; } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLSocket_shutdownNative( JNIEnv *env, jobject self, jint how) { JSSL_SocketData *sock = NULL; PRStatus status; if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) goto finish; status = PR_Shutdown(sock->fd, JSSL_enums[how]); if( status != PR_SUCCESS) { JSSL_throwSSLSocketException(env, "Failed to shutdown socket"); goto finish; } finish: EXCEPTION_CHECK(env, sock) return; } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLSocket_invalidateSession(JNIEnv *env, jobject self) { JSSL_SocketData *sock = NULL; SECStatus status; if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) goto finish; status = SSL_InvalidateSession(sock->fd); if(status != SECSuccess) { JSSL_throwSSLSocketException(env, "Failed to invalidate session"); goto finish; } finish: EXCEPTION_CHECK(env, sock) return; } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLSocket_redoHandshake( JNIEnv *env, jobject self, jboolean flushCache) { JSSL_SocketData *sock = NULL; SECStatus status; if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) goto finish; status = SSL_ReHandshake(sock->fd, flushCache); if(status != SECSuccess) { JSSL_throwSSLSocketException(env, "Failed to redo handshake"); goto finish; } finish: EXCEPTION_CHECK(env, sock) return; } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLSocket_resetHandshakeNative( JNIEnv *env, jobject self, jboolean asClient) { JSSL_SocketData *sock = NULL; SECStatus status; if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) goto finish; status = SSL_ResetHandshake(sock->fd, !asClient); if(status != SECSuccess) { JSSL_throwSSLSocketException(env, "Failed to redo handshake"); goto finish; } finish: EXCEPTION_CHECK(env, sock) return; } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SSLSocket_setCipherPolicyNative( JNIEnv *env, jobject self, jint policyEnum) { SECStatus status; switch(policyEnum) { case SSL_POLICY_DOMESTIC: status = NSS_SetDomesticPolicy(); break; case SSL_POLICY_EXPORT: status = NSS_SetExportPolicy(); break; case SSL_POLICY_FRANCE: status = NSS_SetFrancePolicy(); break; default: PR_ASSERT(PR_FALSE); status = SECFailure; } if(status != SECSuccess) { JSSL_throwSSLSocketException(env, "Failed to set cipher policy"); goto finish; } finish: return; } JNIEXPORT jintArray JNICALL Java_org_mozilla_jss_ssl_SSLSocket_getImplementedCipherSuites (JNIEnv *env, jclass clazz) { jintArray ciphArray = NULL; jint* arrayRegion = NULL; int i; ciphArray = (*env)->NewIntArray(env, SSL_NumImplementedCiphers); if( ciphArray == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } arrayRegion = (*env)->GetIntArrayElements(env, ciphArray, NULL/*isCopy*/); if( arrayRegion == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } for( i=0; i < SSL_NumImplementedCiphers; ++i) { arrayRegion[i] = SSL_ImplementedCiphers[i]; } finish: if( arrayRegion != NULL ) { (*env)->ReleaseIntArrayElements(env, ciphArray, arrayRegion, 0); } return ciphArray; } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLSocket.java000066400000000000000000001713771412550063600233040ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.ssl; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.SocketException; import java.net.SocketTimeoutException; import java.util.ArrayList; import java.util.Collection; /** * SSL client socket. */ public class SSLSocket extends java.net.Socket { /** * * Note the following cipher-suites constants are not all implemented. * You need to call getImplementedCiphersuites. * */ public static final int SSL2_RC4_128_WITH_MD5 = 0xFF01; public static final int SSL2_RC4_128_EXPORT40_WITH_MD5 = 0xFF02; public static final int SSL2_RC2_128_CBC_WITH_MD5 = 0xFF03; public static final int SSL2_RC2_128_CBC_EXPORT40_WITH_MD5 = 0xFF04; public static final int SSL2_IDEA_128_CBC_WITH_MD5 = 0xFF05; public static final int SSL2_DES_64_CBC_WITH_MD5 = 0xFF06; public static final int SSL2_DES_192_EDE3_CBC_WITH_MD5 = 0xFF07; public static final int TLS_NULL_WITH_NULL_NULL = 0x0000; /** * @deprecated Replaced with TLS_RSA_WITH_NULL_MD5. */ @Deprecated public static final int SSL3_RSA_WITH_NULL_MD5 = 0x0001; public static final int TLS_RSA_WITH_NULL_MD5 = 0x0001; /** * @deprecated Replaced with TLS_RSA_WITH_NULL_SHA. */ @Deprecated public static final int SSL3_RSA_WITH_NULL_SHA = 0x0002; public static final int TLS_RSA_WITH_NULL_SHA = 0x0002; public static final int SSL3_RSA_EXPORT_WITH_RC4_40_MD5 = 0x0003; public static final int TLS_RSA_EXPORT_WITH_RC4_40_MD5 = 0x0003; /** * @deprecated Replaced with TLS_RSA_WITH_RC4_128_MD5. */ @Deprecated public static final int SSL3_RSA_WITH_RC4_128_MD5 = 0x0004; public static final int TLS_RSA_WITH_RC4_128_MD5 = 0x0004; /** * @deprecated Replaced with TLS_RSA_WITH_RC4_128_SHA. */ @Deprecated public static final int SSL3_RSA_WITH_RC4_128_SHA = 0x0005; public static final int TLS_RSA_WITH_RC4_128_SHA = 0x0005; public static final int SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 0x0006; public static final int TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 0x0006; /** * @deprecated Replaced with TLS_RSA_WITH_IDEA_CBC_SHA. */ @Deprecated public static final int SSL3_RSA_WITH_IDEA_CBC_SHA = 0x0007; public static final int TLS_RSA_WITH_IDEA_CBC_SHA = 0x0007; public static final int SSL3_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0008; public static final int TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0008; /** * @deprecated Replaced with TLS_RSA_WITH_DES_CBC_SHA. */ @Deprecated public static final int SSL3_RSA_WITH_DES_CBC_SHA = 0x0009; public static final int TLS_RSA_WITH_DES_CBC_SHA = 0x0009; /** * @deprecated Replaced with TLS_RSA_WITH_3DES_EDE_CBC_SHA. */ @Deprecated public static final int SSL3_RSA_WITH_3DES_EDE_CBC_SHA = 0x000a; public static final int TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000a; public static final int SSL3_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x000b; public static final int TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x000b; /** * @deprecated Replaced with TLS_DH_DSS_WITH_DES_CBC_SHA. */ @Deprecated public static final int SSL3_DH_DSS_WITH_DES_CBC_SHA = 0x000c; public static final int TLS_DH_DSS_WITH_DES_CBC_SHA = 0x000c; /** * @deprecated Replaced with TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA. */ @Deprecated public static final int SSL3_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000d; public static final int TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000d; public static final int SSL3_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x000e; public static final int TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x000e; /** * @deprecated Replaced with TLS_DH_RSA_WITH_DES_CBC_SHA. */ @Deprecated public static final int SSL3_DH_RSA_WITH_DES_CBC_SHA = 0x000f; public static final int TLS_DH_RSA_WITH_DES_CBC_SHA = 0x000f; /** * @deprecated Replaced with TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA. */ @Deprecated public static final int SSL3_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010; public static final int TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010; public static final int SSL3_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x0011; public static final int TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x0011; /** * @deprecated Replaced with TLS_DHE_DSS_WITH_DES_CBC_SHA. */ @Deprecated public static final int SSL3_DHE_DSS_WITH_DES_CBC_SHA = 0x0012; public static final int TLS_DHE_DSS_WITH_DES_CBC_SHA = 0x0012; /** * @deprecated Replaced with TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA. */ @Deprecated public static final int SSL3_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013; public static final int TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013; public static final int SSL3_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0014; public static final int TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0014; /** * @deprecated Replaced with TLS_DHE_RSA_WITH_DES_CBC_SHA. */ @Deprecated public static final int SSL3_DHE_RSA_WITH_DES_CBC_SHA = 0x0015; public static final int TLS_DHE_RSA_WITH_DES_CBC_SHA = 0x0015; /** * @deprecated Replaced with TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA. */ @Deprecated public static final int SSL3_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016; public static final int TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016; public static final int SSL3_DH_ANON_EXPORT_WITH_RC4_40_MD5 = 0x0017; public static final int TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = 0x0017; /** * @deprecated Replaced with TLS_DH_anon_WITH_RC4_128_MD5. */ @Deprecated public static final int SSL3_DH_ANON_WITH_RC4_128_MD5 = 0x0018; public static final int TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018; public static final int SSL3_DH_ANON_EXPORT_WITH_DES40_CBC_SHA = 0x0019; public static final int TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 0x0019; /** * @deprecated Replaced with TLS_DH_anon_WITH_DES_CBC_SHA. */ @Deprecated public static final int SSL3_DH_ANON_WITH_DES_CBC_SHA = 0x001a; public static final int TLS_DH_anon_WITH_DES_CBC_SHA = 0x001a; /** * @deprecated Replaced with TLS_DH_anon_WITH_3DES_EDE_CBC_SHA. */ @Deprecated public static final int SSL3_DH_ANON_WITH_3DES_EDE_CBC_SHA = 0x001b; public static final int TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x001b; /** * @deprecated As of NSS 3.11, FORTEZZA is no longer supported. */ @Deprecated public static final int SSL3_FORTEZZA_DMS_WITH_NULL_SHA = 0x001c; /** * @deprecated As of NSS 3.11, FORTEZZA is no longer supported. */ @Deprecated public static final int SSL3_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA = 0x001d; /** * @deprecated As of NSS 3.11, FORTEZZA is no longer supported. */ @Deprecated public static final int SSL3_FORTEZZA_DMS_WITH_RC4_128_SHA = 0x001e; public static final int SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA = 0xfeff; public static final int SSL_RSA_FIPS_WITH_DES_CBC_SHA = 0xfefe; public static final int TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA = 0x0062; public static final int TLS_RSA_EXPORT1024_WITH_RC4_56_SHA = 0x0064; public static final int TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA = 0x0063; public static final int TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA = 0x0065; public static final int TLS_DHE_DSS_WITH_RC4_128_SHA = 0x0066; public static final int TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067; public static final int TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A; public static final int TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B; // New TLS cipher suites in NSS 3.4 public static final int TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F; public static final int TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x0030; public static final int TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x0031; public static final int TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032; public static final int TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033; /** * @deprecated Replaced with TLS_DH_anon_WITH_AES_128_CBC_SHA. */ @Deprecated public static final int TLS_DH_ANON_WITH_AES_128_CBC_SHA = 0x0034; public static final int TLS_DH_anon_WITH_AES_128_CBC_SHA = 0x0034; public static final int TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035; public static final int TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x0036; public static final int TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x0037; public static final int TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038; public static final int TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039; /** * @deprecated Replaced with TLS_DH_anon_WITH_AES_256_CBC_SHA. */ @Deprecated public static final int TLS_DH_ANON_WITH_AES_256_CBC_SHA = 0x003A; public static final int TLS_DH_anon_WITH_AES_256_CBC_SHA = 0x003A; public static final int TLS_RSA_WITH_NULL_SHA256 = 0x003B; public static final int TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C; public static final int TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D; public static final int TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040; public static final int TLS_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0041; public static final int TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0042; public static final int TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0043; public static final int TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0044; public static final int TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0045; /** * @deprecated Replaced with TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA. */ @Deprecated public static final int TLS_DH_ANON_WITH_CAMELLIA_128_CBC_SHA = 0x0046; public static final int TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA = 0x0046; public static final int TLS_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0084; public static final int TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0085; public static final int TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0086; public static final int TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0087; public static final int TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0088; /** * @deprecated Replaced with TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA. */ @Deprecated public static final int TLS_DH_ANON_WITH_CAMELLIA_256_CBC_SHA = 0x0089; public static final int TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA = 0x0089; public static final int TLS_RSA_WITH_SEED_CBC_SHA = 0x0096; public static final int TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C; public static final int TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D; public static final int TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E; public static final int TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F; public static final int TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2; public static final int TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3; public static final int TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = 0x00AA; public static final int TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 = 0x00AB; public static final int TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF; public static final int TLS_FALLBACK_SCSV = 0x5600; public static final int TLS_ECDH_ECDSA_WITH_NULL_SHA = 0xc001; public static final int TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0xc002; public static final int TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xc003; public static final int TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0xc004; public static final int TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0xc005; public static final int TLS_ECDHE_ECDSA_WITH_NULL_SHA = 0xc006; public static final int TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xc007; public static final int TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xc008; public static final int TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xc009; public static final int TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xc00a; public static final int TLS_ECDH_RSA_WITH_NULL_SHA = 0xc00b; public static final int TLS_ECDH_RSA_WITH_RC4_128_SHA = 0xc00c; public static final int TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 0xc00d; public static final int TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 0xc00e; public static final int TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0xc00f; public static final int TLS_ECDHE_RSA_WITH_NULL_SHA = 0xc010; public static final int TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xc011; public static final int TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xc012; public static final int TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xc013; public static final int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xc014; public static final int TLS_ECDH_anon_WITH_NULL_SHA = 0xc015; public static final int TLS_ECDH_anon_WITH_RC4_128_SHA = 0xc016; public static final int TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = 0xc017; public static final int TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xc018; public static final int TLS_ECDH_anon_WITH_AES_256_CBC_SHA = 0xc019; public static final int TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xc023; public static final int TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xc024; public static final int TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xc027; public static final int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xc028; public static final int TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xc02B; public static final int TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xc02C; public static final int TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = 0xc02D; public static final int TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xc02F; public static final int TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xc030; public static final int TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = 0xc031; /* draft-ietf-tls-chacha20-poly1305-04 */ public static final int TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA8; public static final int TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCA9; public static final int TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAA; public static final int TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAC; public static final int TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xCCAD; public static final int TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256 = 0xD001; public static final int TLS_ECDHE_PSK_WITH_AES_256_GCM_SHA384 = 0xD002; /* Special TLS 1.3 cipher suites that really just specify AEAD */ public static final int TLS_AES_128_GCM_SHA256 = 0x1301; public static final int TLS_AES_256_GCM_SHA384 = 0x1302; public static final int TLS_CHACHA20_POLY1305_SHA256 = 0x1303; /* * Locking strategy of SSLSocket * * isClosed, inRead, and inWrite must be accessed with the object * locked. * * readLock must be locked throughout the read method. It is used * to serialize read calls. * * writeLock must be locked throughout the write method. It is used * to serialize write calls. */ private java.lang.Object readLock = new java.lang.Object(); private java.lang.Object writeLock = new java.lang.Object(); private boolean isClosed = false; private boolean inRead = false; private boolean inWrite = false; private InetAddress inetAddress; private int port; private SocketProxy sockProxy = null; private boolean open = false; private boolean handshakeAsClient = true; private SocketBase base = new SocketBase(); public static final int SSL_REQUIRE_NEVER = org.mozilla.jss.ssl.SocketBase.SSL_REQUIRE_NEVER; public static final int SSL_REQUIRE_ALWAYS = org.mozilla.jss.ssl.SocketBase.SSL_REQUIRE_ALWAYS; public static final int SSL_REQUIRE_FIRST_HANDSHAKE = org.mozilla.jss.ssl.SocketBase.SSL_REQUIRE_FIRST_HANDSHAKE; public static final int SSL_REQUIRE_NO_ERROR = org.mozilla.jss.ssl.SocketBase.SSL_REQUIRE_NO_ERROR; public static final int SSL_RENEGOTIATE_NEVER = org.mozilla.jss.ssl.SocketBase.SSL_RENEGOTIATE_NEVER; public static final int SSL_RENEGOTIATE_REQUIRES_XTN = org.mozilla.jss.ssl.SocketBase.SSL_RENEGOTIATE_REQUIRES_XTN; public static final int SSL_RENEGOTIATE_UNRESTRICTED = org.mozilla.jss.ssl.SocketBase.SSL_RENEGOTIATE_UNRESTRICTED; public static final int SSL_RENEGOTIATE_TRANSITIONAL = org.mozilla.jss.ssl.SocketBase.SSL_RENEGOTIATE_TRANSITIONAL; private Collection socketListeners = new ArrayList<>(); private Collection handshakeCompletedListeners = new ArrayList<>(); /** * For sockets that get created by accept(). */ SSLSocket() { } /** * Should only be called by SSLServerSocket after a successful * accept(). */ void setSockProxy(SocketProxy sp) { sockProxy = sp; base.setProxy(sp); } /** * Creates an SSL client socket and connects to the specified host and * port. * * @param host The hostname to connect to. * @param port The port to connect to. */ public SSLSocket(String host, int port) throws IOException { this(InetAddress.getByName(host), port, null, 0); } /** * Creates an SSL client socket and connects to the specified address and * port. * * @param address The IP address to connect to. * @param port The port to connect to. */ public SSLSocket(InetAddress address, int port) throws IOException { this(address, port, null, 0); } /** * Creates an SSL client socket and connects to the specified host and * port. Binds to the given local address and port. * * @param host The hostname to connect to. * @param port The port to connect to. * @param localAddr The local address to bind to. It can be null, in which * case an unspecified local address will be chosen. * @param localPort The local port to bind to. If 0, a random port will be * assigned to the socket. */ public SSLSocket(String host, int port, InetAddress localAddr, int localPort) throws IOException { this(InetAddress.getByName(host), port, localAddr, localPort); } /** * Creates an SSL client socket and connects to the specified address and * port. Binds to the given local address and port. * * @param address The IP address to connect to. * @param port The port to connect to. * @param localAddr The local address to bind to. It can be null, in which * case an unspecified local address will be chosen. * @param localPort The local port to bind to. If 0, a random port will be * assigned to the socket. */ public SSLSocket(InetAddress address, int port, InetAddress localAddr, int localPort) throws IOException { this(address, port, localAddr, localPort, null, null); } /** * Creates an SSL client socket and connects to the specified host and * port. Binds to the given local address and port. Installs the given * callbacks for certificate approval and client certificate selection. * * @param host The hostname to connect to. * @param port The port to connect to. * @param localAddr The local address to bind to. It can be null, in which * case an unspecified local address will be chosen. * @param localPort The local port to bind to. If 0, a random port will be * assigned to the socket. * @param certApprovalCallback A callback that can be used to override * approval of the peer's certificate. * @param clientCertSelectionCallback A callback to select the client * certificate to present to the peer. */ public SSLSocket(String host, int port, InetAddress localAddr, int localPort, SSLCertificateApprovalCallback certApprovalCallback, SSLClientCertificateSelectionCallback clientCertSelectionCallback) throws IOException { this(InetAddress.getByName(host), port, localAddr, localPort, certApprovalCallback, clientCertSelectionCallback); } /** * Creates an SSL client socket and connects to the specified address and * port. Binds to the given local address and port. Installs the given * callbacks for certificate approval and client certificate selection. * * @param address The IP address to connect to. * @param port The port to connect to. * @param localAddr The local address to bind to. It can be null, in which * case an unspecified local address will be chosen. * @param localPort The local port to bind to. If 0, a random port will be * assigned to the socket. * @param stream This parameter is ignored. All SSLSockets are stream * sockets. * @param certApprovalCallback A callback that can be used to override * approval of the peer's certificate. * @param clientCertSelectionCallback A callback to select the client * certificate to present to the peer. * @deprecated As of JSS 3.0. The stream parameter is ignored, because * only stream sockets are supported. */ @Deprecated public SSLSocket(InetAddress address, int port, InetAddress localAddr, int localPort, boolean stream, SSLCertificateApprovalCallback certApprovalCallback, SSLClientCertificateSelectionCallback clientCertSelectionCallback) throws IOException { this(address, port, localAddr, localPort, certApprovalCallback, clientCertSelectionCallback); } /** * Creates an SSL client socket and connects to the specified address and * port. Binds to the given local address and port. Installs the given * callbacks for certificate approval and client certificate selection. * * @param address The IP address to connect to. * @param port The port to connect to. * @param localAddr The local address to bind to. It can be null, in which * case an unspecified local address will be chosen. * @param localPort The local port to bind to. If 0, a random port will be * assigned to the socket. * @param certApprovalCallback A callback that can be used to override * approval of the peer's certificate. * @param clientCertSelectionCallback A callback to select the client * certificate to present to the peer. */ public SSLSocket(InetAddress address, int port, InetAddress localAddr, int localPort, SSLCertificateApprovalCallback certApprovalCallback, SSLClientCertificateSelectionCallback clientCertSelectionCallback) throws IOException { this(address, address.getHostName(), port, localAddr, localPort, certApprovalCallback, clientCertSelectionCallback); } private SSLSocket(InetAddress address, String hostname, int port, InetAddress localAddr, int localPort, SSLCertificateApprovalCallback certApprovalCallback, SSLClientCertificateSelectionCallback clientCertSelectionCallback) throws IOException { int socketFamily = SocketBase.SSL_AF_INET; if (SocketBase.supportsIPV6()) { socketFamily = SocketBase.SSL_AF_INET6; } // create the socket sockProxy = new SocketProxy( base.socketCreate( this, certApprovalCallback, clientCertSelectionCallback, socketFamily)); base.setProxy(sockProxy); // bind it to local address and port if (localAddr != null || localPort > 0) { // bind because they specified a local address byte[] addrBA = null; if (localAddr != null) { addrBA = localAddr.getAddress(); } base.socketBind(addrBA, localPort); } /* connect to the remote socket */ socketConnect(address.getAddress(), hostname, port); } /** * Creates an SSL client socket using the given Java socket for underlying * I/O. Installs the given callbacks for certificate approval and * client certificate selection. * * @param s The Java socket to use for underlying I/O. * @param host The hostname of the remote side of the connection. * This name is used to verify the server's certificate. * @param certApprovalCallback A callback that can be used to override * approval of the peer's certificate. * @param clientCertSelectionCallback A callback to select the client * certificate to present to the peer. */ public SSLSocket(java.net.Socket s, String host, SSLCertificateApprovalCallback certApprovalCallback, SSLClientCertificateSelectionCallback clientCertSelectionCallback) throws IOException { // create the socket sockProxy = new SocketProxy( base.socketCreate( this, certApprovalCallback, clientCertSelectionCallback, s, host, SocketBase.SSL_AF_INET)); base.setProxy(sockProxy); resetHandshake(); } /** * @return The remote peer's IP address or null if the SSLSocket is closed. */ @Override public InetAddress getInetAddress() { synchronized (this) { if (isClosed) { return null; } return base.getInetAddress(); } } /** * @return The local IP address or null if the SSLSocket is closed. */ @Override public InetAddress getLocalAddress() { synchronized (this) { if (isClosed) { return null; } return base.getLocalAddress(); } } /** * @return The local port or -1 if the SSLSocket is closed. */ @Override public int getLocalPort() { synchronized (this) { if (isClosed) { return -1; } return base.getLocalPort(); } } /** * @return The remote port. */ @Override public native int getPort(); /** * Returns the input stream for reading from this socket. */ @Override public InputStream getInputStream() throws IOException { return new SSLInputStream(this); } /** * Returns the output stream for writing to this socket. */ @Override public OutputStream getOutputStream() throws IOException { return new SSLOutputStream(this); } /** * Enables or disables the TCP_NO_DELAY socket option. Enabling this * option will disable the Nagle algorithm. */ @Override public native void setTcpNoDelay(boolean on) throws SocketException; /** * Returns the current setting of the TCP_NO_DELAY socket option. */ @Override public native boolean getTcpNoDelay() throws SocketException; /** * Enables or disables the SO_KEEPALIVE socket option. */ @Override public native void setKeepAlive(boolean on) throws SocketException; /** * Returns the current setting of the SO_KEEPALIVE socket option. */ @Override public native boolean getKeepAlive() throws SocketException; /** * Shuts down the input side of the socket. */ @Override public void shutdownInput() throws IOException { shutdownNative(SocketBase.PR_SHUTDOWN_RCV); } /** * Shuts down the output side of the socket. */ @Override public void shutdownOutput() throws IOException { shutdownNative(SocketBase.PR_SHUTDOWN_SEND); } private native void shutdownNative(int how) throws IOException; private native void abortReadWrite() throws IOException; /** * Sets the SO_LINGER socket option. * param linger The time (in seconds) to linger for. */ @Override public native void setSoLinger(boolean on, int linger) throws SocketException; /** * Returns the current value of the SO_LINGER socket option. */ @Override public native int getSoLinger() throws SocketException; /** * Sets the SO_TIMEOUT socket option. * * @param timeout The timeout time in milliseconds. */ @Override public synchronized void setSoTimeout(int timeout) throws SocketException { base.setTimeout(timeout); } /** * Returns the current value of the SO_TIMEOUT socket option. * * @return The timeout time in milliseconds. */ @Override public synchronized int getSoTimeout() throws SocketException { return base.getTimeout(); } /** * Sets the size (in bytes) of the send buffer. */ @Override public synchronized native void setSendBufferSize(int size) throws SocketException; /** * Returns the size (in bytes) of the send buffer. */ @Override public synchronized native int getSendBufferSize() throws SocketException; /** * Sets the size (in bytes) of the receive buffer. */ @Override public synchronized native void setReceiveBufferSize(int size) throws SocketException; /** * Returns the size (in bytes) of the receive buffer. */ @Override public synchronized native int getReceiveBufferSize() throws SocketException; /** * Closes this socket. */ @Override public void close() throws IOException { synchronized (this) { if (isClosed) { /* finalize calls close or user calls close more than once */ return; } isClosed = true; if (sockProxy == null) { /* nothing to do */ return; } /* * If a read or write is occurring, abort the I/O. Any * further attempts to read/write will fail since isClosed * is true */ if (inRead || inWrite) { abortReadWrite(); } } /* * Lock readLock and writeLock to ensure that read and write * have been aborted. */ synchronized (readLock) { synchronized (writeLock) { base.close(); sockProxy = null; base.setProxy(null); } } } private native void socketConnect(byte[] addr, String hostname, int port) throws SocketException; //////////////////////////////////////////////////////////////////// // SSL-specific stuff //////////////////////////////////////////////////////////////////// public void addSocketListener(SSLSocketListener listener) { socketListeners.add(listener); addHandshakeCompletedListener(listener); } public void removeSocketListener(SSLSocketListener listener) { socketListeners.remove(listener); removeHandshakeCompletedListener(listener); } private void fireAlertReceivedEvent(SSLAlertEvent event) { for (SSLSocketListener listener : socketListeners) { listener.alertReceived(event); } } private void fireAlertSentEvent(SSLAlertEvent event) { for (SSLSocketListener listener : socketListeners) { listener.alertSent(event); } } /** * Adds a listener to be notified when an SSL handshake completes. */ public void addHandshakeCompletedListener(SSLHandshakeCompletedListener listener) { handshakeCompletedListeners.add(listener); } /** * Removes a previously registered listener for handshake completion. */ public void removeHandshakeCompletedListener(SSLHandshakeCompletedListener listener) { handshakeCompletedListeners.remove(listener); } private void notifyAllHandshakeListeners() { SSLHandshakeCompletedEvent event = new SSLHandshakeCompletedEvent(this); for (SSLHandshakeCompletedListener listener : handshakeCompletedListeners) { listener.handshakeCompleted(event); } } /** * Enables SSL v2 on this socket. It is enabled by default, unless the * default has been changed with enableSSL2Default. */ public void enableSSL2(boolean enable) throws SocketException { base.enableSSL2(enable); } /** * Sets the default for SSL v2 for all new sockets. */ static public void enableSSL2Default(boolean enable) throws SocketException { setSSLDefaultOption(SocketBase.SSL_ENABLE_SSL2, enable); } /** * Enables SSL v3 on this socket. It is enabled by default, unless the * default has been changed with enableSSL3Default. */ public void enableSSL3(boolean enable) throws SocketException { base.enableSSL3(enable); } /** * Sets the default for SSL v3 for all new sockets. */ static public void enableSSL3Default(boolean enable) throws SocketException { setSSLDefaultOption(SocketBase.SSL_ENABLE_SSL3, enable); } /** * Enables TLS on this socket. It is enabled by default, unless the * default has been changed with enableTLSDefault. */ public void enableTLS(boolean enable) throws SocketException { base.enableTLS(enable); } /** * Sets the default for TLS for all new sockets. */ static public void enableTLSDefault(boolean enable) throws SocketException { setSSLDefaultOption(SocketBase.SSL_ENABLE_TLS, enable); } /** * Enables Session tickets on this socket. It is disabled by default, * unless the default has been changed with * enableSessionTicketsDefault. */ public void enableSessionTickets(boolean enable) throws SocketException { base.enableSessionTickets(enable); } /** * Sets the default for Session Tickets for all new sockets. */ static public void enableSessionTicketsDefault(boolean enable) throws SocketException { setSSLDefaultOption(SocketBase.SSL_ENABLE_SESSION_TICKETS, enable); } /** * Enables the mode of renegotiation that the peer must use on this * socket. Default is never renegotiate at all. Unless the default has * been changed with SSLSocket.enableRenegotiationDefault. * * @param mode One of: * SSLSocket.SSL_RENEGOTIATE_NEVER - Never renegotiate at all. * * SSLSocket.SSL_RENEGOTIATE_UNRESTRICTED - Renegotiate without * restriction, whether or not the peer's hello bears the TLS * renegotiation info extension. Vulnerable, as in the past. * * SSLSocket.SSL_RENEGOTIATE_REQUIRES_XTN - Only renegotiate if the * peer's hello bears the TLS renegotiation_info extension. This is * safe renegotiation. * * SSLSocket.SSL_RENEGOTIATE_TRANSITIONAL - Disallow unsafe * renegotiation in server sockets only, but allow clients * to continue to renegotiate with vulnerable servers. * This value should only be used during the transition period * when few servers have been upgraded. */ public void enableRenegotiation(int mode) throws SocketException { if (mode >= SocketBase.SSL_RENEGOTIATE_NEVER && mode <= SocketBase.SSL_RENEGOTIATE_TRANSITIONAL) { base.enableRenegotiation(mode); } else { throw new SocketException("Incorrect input value."); } } /** * Set the mode of renegotiation that the peer must use for all new * sockets. The default is never renegotiate at all. * * @param mode One of: * SSLSocket.SSL_RENEGOTIATE_NEVER - Never renegotiate at all. * * SSLSocket.SSL_RENEGOTIATE_UNRESTRICTED - Renegotiate without * restriction, whether or not the peer's hello bears the TLS * renegotiation info extension. Vulnerable, as in the past. * * SSLSocket.SSL_RENEGOTIATE_REQUIRES_XTN - Only renegotiate if the * peer's hello bears the TLS renegotiation_info extension. This is * safe renegotiation. * * SSLSocket.SSL_RENEGOTIATE_TRANSITIONAL - Disallow unsafe * renegotiation in server sockets only, but allow clients * to continue to renegotiate with vulnerable servers. * This value should only be used during the transition period * when few servers have been upgraded. */ static public void enableRenegotiationDefault(int mode) throws SocketException { if (mode >= SocketBase.SSL_RENEGOTIATE_NEVER && mode <= SocketBase.SSL_RENEGOTIATE_TRANSITIONAL) { setSSLDefaultOptionMode(SocketBase.SSL_ENABLE_RENEGOTIATION, mode); } else { throw new SocketException("Incorrect input value."); } } /** * For this socket require that the peer must send * Signaling Cipher Suite Value (SCSV) or Renegotiation Info (RI) * extension in ALL handshakes. It is disabled by default, * unless the default has been changed with * SSLSocket.enableRequireSafeNegotiationDefault. */ public void enableRequireSafeNegotiation(boolean enable) throws SocketException { base.enableRequireSafeNegotiation(enable); } /** * For this socket require that the peer must send * Signaling Cipher Suite Value (SCSV) or Renegotiation Info (RI) * extension in ALL handshakes. It is disabled by default. */ static public void enableRequireSafeNegotiationDefault(boolean enable) throws SocketException { setSSLDefaultOption(SocketBase.SSL_REQUIRE_SAFE_NEGOTIATION, enable); } /** * Enable rollback detection for this socket. * It is enabled by default, unless the default has been changed * with enableRollbackDetectionDefault. */ public void enableRollbackDetection(boolean enable) throws SocketException { base.enableRollbackDetection(enable); } /** * Sets the default rollback detection for all new sockets. */ static void enableRollbackDetectionDefault(boolean enable) throws SocketException { setSSLDefaultOption(SocketBase.SSL_ROLLBACK_DETECTION, enable); } /** * This option, enableStepDown, is concerned with the generation * of step-down keys which are used with export suites. * If the server cert's public key is 512 bits or less * this option is ignored because step-down keys don't * need to be generated. * If the server cert's public key is more than 512 bits, * this option has the following effect: * enable=true: generate step-down keys * enable=false: don't generate step-down keys; disable * export cipher suites * * This option is enabled by default; unless the default has * been changed with SSLSocket.enableStepDownDefault. */ public void enableStepDown(boolean enable) throws SocketException { base.enableStepDown(enable); } /** * This option, enableStepDownDefault, is concerned with the * generation of step-down keys which are used with export suites. * This options will set the default for all sockets. * If the server cert's public key is 512 bits of less, * this option is ignored because step-down keys don't * need to be generated. * If the server cert's public key is more than 512 bits, * this option has the following effect: * enable=true: generate step-down keys * enable=false: don't generate step-down keys; disable * export cipher suites * * This option is enabled by default for all sockets. */ static void enableStepDownDefault(boolean enable) throws SocketException { setSSLDefaultOption(SocketBase.SSL_NO_STEP_DOWN, enable); } /** * Enable simultaneous read/write by separate read and write threads * (full duplex) for this socket. * It is disabled by default, unless the default has been changed * with enableFDXDefault. */ public void enableFDX(boolean enable) throws SocketException { base.enableFDX(enable); } /** * Sets the default to permit simultaneous read/write * by separate read and write threads (full duplex) * for all new sockets. */ static void enableFDXDefault(boolean enable) throws SocketException { setSSLDefaultOption(SocketBase.SSL_ENABLE_FDX, enable); } /** * Enable sending v3 client hello in v2 format for this socket. * It is enabled by default, unless the default has been changed * with enableV2CompatibleHelloDefault. */ public void enableV2CompatibleHello(boolean enable) throws SocketException { base.enableV2CompatibleHello(enable); } /** * Sets the default to send v3 client hello in v2 format * for all new sockets. */ static void enableV2CompatibleHelloDefault(boolean enable) throws SocketException { setSSLDefaultOption(SocketBase.SSL_V2_COMPATIBLE_HELLO, enable); } /** * Enable or disable post-handshake auth for a single socket. */ public void enablePostHandshakeAuth(boolean enable) throws SocketException { base.enablePostHandshakeAuth(enable); } /** * Sets the default to allow post-handshake auth globally. */ public static void enablePostHandshakeAuthDefault(boolean enable) throws SocketException { setSSLDefaultOption(SocketBase.SSL_ENABLE_POST_HANDSHAKE_AUTH, enable); } /** * @return a String listing the current SSLOptions for this SSLSocket. */ public String getSSLOptions() { return base.getSSLOptions(); } /** * * @param option * @return 0 for option disabled 1 for option enabled. */ static private native int getSSLDefaultOption(int option) throws SocketException; /** * * @return a String listing the Default SSLOptions for all SSLSockets. */ static public String getSSLDefaultOptions() { StringBuffer buf = new StringBuffer(); try { buf.append("Default Options configured for all SSLSockets: "); buf.append("\nSSL_ENABLE_SSL2" + ((getSSLDefaultOption(SocketBase.SSL_ENABLE_SSL2) != 0) ? "=on" : "=off")); buf.append("\nSSL_ENABLE_SSL3" + ((getSSLDefaultOption(SocketBase.SSL_ENABLE_SSL3) != 0) ? "=on" : "=off")); buf.append("\nSSL_ENABLE_TLS" + ((getSSLDefaultOption(SocketBase.SSL_ENABLE_TLS) != 0) ? "=on" : "=off")); buf.append("\nSSL_ENABLE_SESSION_TICKETS" + ((getSSLDefaultOption(SocketBase.SSL_ENABLE_SESSION_TICKETS) != 0) ? "=on" : "=off")); buf.append("\nSSL_REQUIRE_CERTIFICATE"); switch (getSSLDefaultOption(SocketBase.SSL_REQUIRE_CERTIFICATE)) { case 0: buf.append("=Never"); break; case 1: buf.append("=Always"); break; case 2: buf.append("=First Handshake"); break; case 3: buf.append("=No Error"); break; default: buf.append("=Report JSS Bug this option has a status."); break; } //end switch buf.append("\nSSL_REQUEST_CERTIFICATE" + ((getSSLDefaultOption(SocketBase.SSL_REQUEST_CERTIFICATE) != 0) ? "=on" : "=off")); buf.append("\nSSL_NO_CACHE" + ((getSSLDefaultOption(SocketBase.SSL_NO_CACHE) != 0) ? "=on" : "=off")); buf.append("\nSSL_ROLLBACK_DETECTION" + ((getSSLDefaultOption(SocketBase.SSL_ROLLBACK_DETECTION) != 0) ? "=on" : "=off")); buf.append("\nSSL_NO_STEP_DOWN" + ((getSSLDefaultOption(SocketBase.SSL_NO_STEP_DOWN) != 0) ? "=on" : "=off")); buf.append("\nSSL_ENABLE_FDX" + ((getSSLDefaultOption(SocketBase.SSL_ENABLE_FDX) != 0) ? "=on" : "=off")); buf.append("\nSSL_V2_COMPATIBLE_HELLO" + ((getSSLDefaultOption(SocketBase.SSL_V2_COMPATIBLE_HELLO) != 0) ? "=on" : "=off")); buf.append("\nSSL_ENABLE_SESSION_TICKETS" + ((getSSLDefaultOption(SocketBase.SSL_ENABLE_SESSION_TICKETS) != 0) ? "=on" : "=off")); buf.append("\nSSL_ENABLE_RENEGOTIATION"); switch (getSSLDefaultOption(SocketBase.SSL_ENABLE_RENEGOTIATION)) { case 0: buf.append("=SSL_RENEGOTIATE_NEVER"); break; case 1: buf.append("=SSL_RENEGOTIATE_UNRESTRICTED"); break; case 2: buf.append("=SSL_RENEGOTIATE_REQUIRES_XTN"); break; case 3: buf.append("=SSL_RENEGOTIATE_TRANSITIONAL"); break; default: buf.append("=Report JSS Bug this option has a status."); break; } //end switch buf.append("\nSSL_REQUIRE_SAFE_NEGOTIATION" + ((getSSLDefaultOption(SocketBase.SSL_REQUIRE_SAFE_NEGOTIATION) != 0) ? "=on" : "=off")); } catch (SocketException e) { buf.append("\ngetSSLDefaultOptions exception " + e.getMessage()); } return buf.toString(); } /** * Sets whether the socket requires client authentication from the remote * peer. If requestClientAuth() has not already been called, this * method will tell the socket to request client auth as well as requiring * it. * * @deprecated use requireClientAuth(int) */ @Deprecated public void requireClientAuth(boolean require, boolean onRedo) throws SocketException { base.requireClientAuth(require, onRedo); } /** * Sets whether the socket requires client authentication from the remote * peer. If requestClientAuth() has not already been called, this method * will tell the socket to request client auth as well as requiring it. * This is only meaningful for the server end of the SSL connection. * During the next handshake, the remote peer will be asked to * authenticate itself with the requirement that was set. * * @param mode One of: SSLSocket.SSL_REQUIRE_NEVER, * SSLSocket.SSL_REQUIRE_ALWAYS, * SSLSocket.SSL_REQUIRE_FIRST_HANDSHAKE, * SSLSocket.SSL_REQUIRE_NO_ERROR */ public void requireClientAuth(int mode) throws SocketException { if (mode >= SocketBase.SSL_REQUIRE_NEVER && mode <= SocketBase.SSL_REQUIRE_NO_ERROR) { base.requireClientAuth(mode); } else { throw new SocketException("Incorrect input value."); } } /** * Sets the default setting for requiring client authorization. * All subsequently created sockets will use this default setting. * * @deprecated use requireClientAuthDefault(int) */ @Deprecated public void requireClientAuthDefault(boolean require, boolean onRedo) throws SocketException { setSSLDefaultOption(SocketBase.SSL_REQUIRE_CERTIFICATE, require ? (onRedo ? 1 : 2) : 0); } /** * Sets the default setting for requiring client authorization. * All subsequently created sockets will use this default setting * This is only meaningful for the server end of the SSL connection. * * @param mode One of: SSLSocket.SSL_REQUIRE_NEVER, * SSLSocket.SSL_REQUIRE_ALWAYS, * SSLSocket.SSL_REQUIRE_FIRST_HANDSHAKE, * SSLSocket.SSL_REQUIRE_NO_ERROR */ static public void requireClientAuthDefault(int mode) throws SocketException { if (mode >= SocketBase.SSL_REQUIRE_NEVER && mode <= SocketBase.SSL_REQUIRE_NO_ERROR) { setSSLDefaultOption(SocketBase.SSL_REQUEST_CERTIFICATE, true); setSSLDefaultOptionMode(SocketBase.SSL_REQUIRE_CERTIFICATE, mode); } else { throw new SocketException("Incorrect input value."); } } /** * Force an already started SSL handshake to complete. * This method should block until the handshake has completed. */ public native void forceHandshake() throws SocketException; /** * Determines whether this end of the socket is the client or the server * for purposes of the SSL protocol. By default, it is the client. * * @param b true if this end of the socket is the SSL slient, false * if it is the SSL server. */ public void setUseClientMode(boolean b) { handshakeAsClient = b; } /** * @return true if this end of the socket is the SSL client, false * if it is the SSL server. */ public boolean getUseClientMode() { return handshakeAsClient; } /** * Resets the handshake state. */ public void resetHandshake() throws SocketException { resetHandshakeNative(handshakeAsClient); } private native void resetHandshakeNative(boolean asClient) throws SocketException; /** * Returns the security status of this socket. */ public native SSLSecurityStatus getStatus() throws SocketException; /** * Sets the nickname of the certificate to use for client authentication. * Alternately, you can specify an SSLClientCertificateSelectionCallback, * which will receive a list of certificates that are valid for client * authentication. * * @see org.mozilla.jss.ssl.SSLClientCertificateSelectionCallback */ public void setClientCertNickname(String nick) throws SocketException { base.setClientCertNickname(nick); } /** * Sets the certificate to use for client authentication. * Alternately, you can specify an SSLClientCertificateSelectionCallback, * which will receive a list of certificates that are valid for client * authentication. * * @see org.mozilla.jss.ssl.SSLClientCertificateSelectionCallback */ public void setClientCert(org.mozilla.jss.crypto.X509Certificate cert) throws SocketException { base.setClientCert(cert); } /** * Enables/disables the request of client authentication. This is only * meaningful for the server end of the SSL connection. During the next * handshake, the remote peer will be asked to authenticate itself. * * @see org.mozilla.jss.ssl.SSLSocket#requireClientAuth */ public void requestClientAuth(boolean b) throws SocketException { base.requestClientAuth(b); } /** * @deprecated As of JSS 3.0. This method is misnamed. Use * requestClientAuth instead. */ @Deprecated public void setNeedClientAuth(boolean b) throws SocketException { base.requestClientAuth(b); } /** * Enables/disables the request of client authentication. This is only * meaningful for the server end of the SSL connection. During the next * handshake, the remote peer will be asked to authenticate itself. *

* In addition, the client certificate's expiration will not * prevent it from being accepted. * * @see org.mozilla.jss.ssl.SSLSocket#requireClientAuth * public void requestClientAuthNoExpiryCheck(boolean b) * throws SocketException * { * base.requestClientAuthNoExpiryCheck(b); * } * * /** * @deprecated As of JSS 3.0. This method is misnamed. Use * requestClientAuthNoExpiryCheck instead. */ @Deprecated public void setNeedClientAuthNoExpiryCheck(boolean b) throws SocketException { base.requestClientAuthNoExpiryCheck(b); } /** * Enables/disables the session cache. By default, the session cache * is enabled. */ public void useCache(boolean b) throws SocketException { base.useCache(b); } /** * Sets the default setting for use of the session cache. */ public void useCacheDefault(boolean b) throws SocketException { setSSLDefaultOption(SocketBase.SSL_NO_CACHE, !b); } public static void setSSLVersionRangeDefault(SSLProtocolVariant ssl_variant, SSLVersionRange range) throws SocketException { if (range == null) throw new SocketException("setSSLVersionRangeDefault: range null"); setSSLVersionRangeDefault( ssl_variant.getEnum(), range.getMinVersion().value(), range.getMaxVersion().value()); } public static SSLVersionRange boundSSLVersionRange(SSLProtocolVariant ssl_variant, SSLVersionRange range) throws SocketException { if (range == null) throw new SocketException("setSSLVersionRangeDefault: range null"); return boundSSLVersionRange( ssl_variant.getEnum(), range.getMinVersion().value(), range.getMaxVersion().value()); } /** * Sets SSL Version Range Default */ private static native void setSSLVersionRangeDefault(int ssl_variant, int min, int max) throws SocketException; /** * Checks SSL Version Range against Default */ private static native SSLVersionRange boundSSLVersionRange(int ssl_variant, int min, int max) throws SocketException; private static void setSSLDefaultOption(int option, boolean on) throws SocketException { setSSLDefaultOption(option, on ? 1 : 0); } /** * Sets SSL Default options that have simple enable/disable values. */ private static native void setSSLDefaultOption(int option, int on) throws SocketException; /** * Set SSL default options that have more modes than enable/disable. */ private static native void setSSLDefaultOptionMode(int option, int mode) throws SocketException; /** * Enables/disables the cipher on this socket. */ public native void setCipherPreference(int cipher, boolean enable) throws SocketException; /** * Returns whether this cipher is enabled or disabled on this socket. */ public native boolean getCipherPreference(int cipher) throws SocketException; /** * Sets the default for whether this cipher is enabled or disabled. */ public static native void setCipherPreferenceDefault(int cipher, boolean enable) throws SocketException; /** * Returns the default for whether this cipher is enabled or disabled. */ public static native boolean getCipherPreferenceDefault(int cipher) throws SocketException; native int socketAvailable() throws IOException; int read(byte[] b, int off, int len) throws IOException, SocketTimeoutException { synchronized (readLock) { synchronized (this) { if (isClosed) { /* abort read if socket is closed */ throw new IOException( "Socket has been closed, and cannot be reused."); } inRead = true; } int iRet; try { iRet = socketRead(b, off, len, base.getTimeout()); } catch (SocketTimeoutException ste) { throw new SocketTimeoutException( "SocketTimeoutException cannot read on socket: " + ste); } catch (IOException ioe) { throw new IOException( "SocketException cannot read on socket: " + ioe.getMessage(), ioe); } finally { synchronized (this) { inRead = false; } } return iRet; } } void write(byte[] b, int off, int len) throws IOException, SocketTimeoutException { synchronized (writeLock) { synchronized (this) { if (isClosed) { /* abort write if socket is closed */ throw new IOException( "Socket has been closed, and cannot be reused."); } inWrite = true; } try { socketWrite(b, off, len, base.getTimeout()); } catch (SocketTimeoutException ste) { throw new SocketTimeoutException( "SocketTimeoutException cannot write on socket: " + ste); } catch (IOException ioe) { throw new IOException( "SocketException cannot write on socket: " + ioe.getMessage(), ioe); } finally { synchronized (this) { inWrite = false; } } } } private native int socketRead(byte[] b, int off, int len, int timeout) throws IOException; private native void socketWrite(byte[] b, int off, int len, int timeout) throws IOException; /** * Removes the current session from the session cache. */ public native void invalidateSession() throws SocketException; /** * Causes SSL to begin a full, new SSL 3.0 handshake from scratch * on a connection that has already completed one handshake. *

* Does not flush the SSL3 cache entry first, so a full handshake * will not take place. Instead only the symmetric session keys will * be regenerated. */ public void redoHandshake() throws SocketException { redoHandshake(false); } /** * Causes SSL to begin a full, new SSL 3.0 handshake from scratch * on a connection that has already completed one handshake. * * @param flushCache If true, this session will be flushed from the cache. * This will force a complete SSL handshake with a private key operation. * If false, only the session key will be regenerated. */ public native void redoHandshake(boolean flushCache) throws SocketException; /** * @deprecated finalize() in Object has been deprecated */ @Override @Deprecated protected void finalize() throws Throwable { close(); /* in case user did not call close */ } /** * Sets the SSL cipher policy. This must be called before creating any * SSL sockets. */ public static void setCipherPolicy(CipherPolicy cp) throws SocketException { setCipherPolicyNative(cp.getEnum()); } private static native void setCipherPolicyNative(int policyEnum) throws SocketException; /** * Returns the addresses and ports of this socket * or an error message if the socket is not in a valid state. */ @Override public String toString() { try { InetAddress inetAddr = getInetAddress(); InetAddress localAddr = getLocalAddress(); int port = getPort(); int localPort = getLocalPort(); StringBuffer buf = new StringBuffer(); buf.append("SSLSocket[addr="); buf.append(inetAddr); buf.append(",localaddr="); buf.append(localAddr); buf.append(",port="); buf.append(port); buf.append(",localport="); buf.append(localPort); buf.append("]"); return buf.toString(); } catch (Exception e) { return "Exception caught in toString(): " + e.getMessage(); } } /** * isFipsCipherSuite * * @return true if the ciphersuite isFIPS, false otherwise */ public static boolean isFipsCipherSuite(int ciphersuite) throws SocketException { return isFipsCipherSuiteNative(ciphersuite); } private static native boolean isFipsCipherSuiteNative(int ciphersuite) throws SocketException; /** * Returns a list of cipher suites that are implemented by NSS. * Each element in the array will be one of the cipher suite constants * defined in this class (for example, * TLS_RSA_WITH_AES_128_CBC_SHA). */ public static native int[] getImplementedCipherSuites(); } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLSocketException.java000066400000000000000000000021411412550063600251410ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.ssl; /** * A subclass of java.net.SocketException that contains an error code * from the native (NSS/NSPR) code. These error codes are defined in the * class org.mozilla.jss.util.NativeErrcodes. * @see org.mozilla.jss.util.NativeErrcodes */ public class SSLSocketException extends java.net.SocketException { private static final long serialVersionUID = 1L; private int errcode = -1; public SSLSocketException() { super(); } public SSLSocketException(String msg) { super(msg); } public SSLSocketException(String msg, int errcode) { super(msg); this.errcode = errcode; } /** * Returns an error code, as defined in class * org.mozilla.jss.util.NativeErrcodes. * @see org.mozilla.jss.util.NativeErrcodes */ public int getErrcode() { return errcode; } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLSocketListener.java000066400000000000000000000006361412550063600247770ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.ssl; public interface SSLSocketListener extends SSLHandshakeCompletedListener { public void alertReceived(SSLAlertEvent event); public void alertSent(SSLAlertEvent event); } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLTest.java000066400000000000000000000063031412550063600227550ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.ssl; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.util.Enumeration; import java.util.Hashtable; import org.mozilla.jss.CryptoManager; public class SSLTest { public static void main(String[] args) { new SSLTest(args); } private Hashtable params = new Hashtable<>(); private String[] defaults = { "port", "443", "host", "www.amazon.com", "remotehost", "www.amazon.com" }; private void initParams() { processArgs(defaults); } private void processArgs(String[] args) { int i; for(i=0; i < args.length; i+=2) { System.out.flush(); params.put(args[i], args[i+1]); } } private void dumpParams() { Enumeration _enum = params.keys(); System.out.println("Parameters:"); while (_enum.hasMoreElements() ) { String key = _enum.nextElement(); System.out.println(key + "=" + params.get(key)); } } public SSLTest(String[] args) { try { initParams(); processArgs(args); dumpParams(); CryptoManager.initialize("."); int port = Integer.valueOf(params.get("port")); Socket s = new Socket(params.get("host"), port); SSLSocket ss = new SSLSocket(s, params.get("remotehost"), null, null); ss.setSoTimeout(5000); OutputStream os = ss.getOutputStream(); String writeString = "GET / HTTP/1.0\n\n"; byte[] writeBytes = writeString.getBytes("8859_1"); os.write(writeBytes); InputStream is = ss.getInputStream(); int numRead = 0; byte[] inbuf = new byte[256]; while( (numRead = is.read(inbuf)) != -1 ) { System.out.print( new String(inbuf, 0, numRead, "UTF-8")); } ss.setKeepAlive(true); ss.setReceiveBufferSize(32000); ss.setSendBufferSize(8000); ss.setSoLinger(true, 10); ss.setTcpNoDelay(true); System.out.println("remote addr is " + ss.getInetAddress().toString()); System.out.println("remote port is " + ss.getPort()); System.out.println("local addr is " + ss.getLocalAddress().toString()); System.out.println("local port is " + ss.getLocalPort()); System.out.println("keepalive is " + ss.getKeepAlive()); System.out.println("receive buffer size is " + ss.getReceiveBufferSize()); System.out.println("send buffer size is " + ss.getSendBufferSize()); System.out.println("solinger is " + ss.getSoLinger()); System.out.println("sotimeout is " + ss.getSoTimeout()); System.out.println("tcpNoDelay is " + ss.getTcpNoDelay()); ss.shutdownInput(); ss.shutdownOutput(); ss.close(); } catch(Exception e) { e.printStackTrace(); } try { Runtime.getRuntime().gc(); }catch(Exception e) { e.printStackTrace(); } } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLVersion.java000066400000000000000000000057731412550063600234750ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.ssl; public enum SSLVersion { /** Aliases ordering is as follows: * [0] - JSS name * [1] - JDK name */ SSL_2_0(new String[] {"SSL2", "SSLv2"}, SocketBase.SSL_LIBRARY_VERSION_2, 0x0002), SSL_3_0(new String[] {"SSL3", "SSLv3"}, SocketBase.SSL_LIBRARY_VERSION_3_0, 0x0300), TLS_1_0(new String[] {"TLS1_0", "TLSv1"}, SocketBase.SSL_LIBRARY_VERSION_TLS_1_0, 0x0301), TLS_1_1(new String[] {"TLS1_1", "TLSv1.1"}, SocketBase.SSL_LIBRARY_VERSION_TLS_1_1, 0x0302), TLS_1_2(new String[] {"TLS1_2", "TLSv1.2"}, SocketBase.SSL_LIBRARY_VERSION_TLS_1_2, 0x0303), TLS_1_3(new String[] {"TLS1_3", "TLSv1.3"}, SocketBase.SSL_LIBRARY_VERSION_TLS_1_3, 0x0304); private String[] aliases; private int value; private int nssValue; private SSLVersion(String alias, int value, int nssValue) { this.aliases = new String[] {alias}; this.value = value; this.nssValue = nssValue; } private SSLVersion(String[] aliases, int value, int nssValue) { this.aliases = aliases; this.value = value; this.nssValue = nssValue; } public String alias() { return aliases[0]; } public String jdkAlias() { return aliases[1]; } public String[] aliases() { return aliases; } public int value() { return value; } public static SSLVersion valueOf(int value) { for (SSLVersion version : SSLVersion.values()) { if (version.value == value) return version; // The only value we'd have issues with is the broken // SSLv2: this could either be SSLv2 or someone passing // the garbage value of SSL_ENABLE_TLS to us. if (version.nssValue == value) return version; } throw new IllegalArgumentException("Invalid SSLVersion value: " + value); } public boolean matchesAlias(String value) { for (String alias : aliases) { if (alias != null && alias.equalsIgnoreCase(value)) { return true; } } return false; } public static SSLVersion findByAlias(String alias) { alias = alias.toUpperCase(); // find by alias for (SSLVersion version : SSLVersion.values()) { if (version.matchesAlias(alias)) { return version; } } // find by name return SSLVersion.valueOf(alias); } public static SSLVersion maxSupported() { SSLVersion result = null; for (SSLVersion v : SSLVersion.values()) { if (result == null || v.compareTo(result) > 0) { result = v; } } return result; } public static SSLVersion minSupported() { return SSLVersion.TLS_1_0; } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLVersionRange.c000066400000000000000000000025541412550063600237450ustar00rootroot00000000000000#include #include #include #include "SSLVersionRange.h" #include "java_ids.h" #include "jssl.h" jobject JSS_SSL_wrapVersionRange(JNIEnv *env, SSLVersionRange vrange) { jobject versionRange = NULL; jclass versionRangeClass = NULL; jmethodID versionRangeCons = NULL; /* * Package the status into a new SSLVersionRange object. */ versionRangeClass = (*env)->FindClass(env, SSL_VERSION_RANGE_CLASS_NAME); PR_ASSERT(versionRangeClass != NULL); if (versionRangeClass == NULL) { /* exception was thrown */ goto finish; } /* * Get a reference to the constructor so we can call it. */ versionRangeCons = (*env)->GetMethodID(env, versionRangeClass, SSL_VERSION_RANGE_CONSTRUCTOR_NAME, SSL_VERSION_RANGE_CONSTRUCTOR_SIG); PR_ASSERT(versionRangeCons != NULL); if (versionRangeCons == NULL) { /* exception was thrown */ goto finish; } /* * Try constructing the new object; returns NULL when construction fails. */ versionRange = (*env)->NewObject(env, versionRangeClass, versionRangeCons, JSSL_enums_reverse(vrange.min), JSSL_enums_reverse(vrange.max)); finish: return versionRange; } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLVersionRange.h000066400000000000000000000007251412550063600237500ustar00rootroot00000000000000#include #include #include #pragma once /* Wrap a NSS SSLVersionRange object into a org.mozilla.jss.ssl.SSLVersionRange object. */ jobject JSS_SSL_wrapVersionRange(JNIEnv *env, SSLVersionRange vrange); // Not implemented: easier to do in Java /* Unwrap a org.mozilla.jss.ssl.SSLVersionRange object and return a NSS SSLVersionRange. */ /* PRStatus JSS_SSL_unwrapVersionRange(JNIEnv *env, jobject range_proxy, SSLVersionRange *vrange); */ jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SSLVersionRange.java000066400000000000000000000066541412550063600244510ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.ssl; import java.util.ArrayList; public class SSLVersionRange { private SSLVersion minVersion; private SSLVersion maxVersion; /** * @deprecated Replaced with SSLVersion.SSL_3_0. */ @Deprecated public static final int ssl3 = SocketBase.SSL_LIBRARY_VERSION_3_0; /** * @deprecated Replaced with SSLVersion.TLS_1_0. */ @Deprecated public static final int tls1_0 = SocketBase.SSL_LIBRARY_VERSION_TLS_1_0; /** * @deprecated Replaced with SSLVersion.TLS_1_1. */ @Deprecated public static final int tls1_1 = SocketBase.SSL_LIBRARY_VERSION_TLS_1_1; /** * @deprecated Replaced with SSLVersion.TLS_1_2. */ @Deprecated public static final int tls1_2 = SocketBase.SSL_LIBRARY_VERSION_TLS_1_2; /** * @deprecated Replaced with SSLVersion.TLS_1_3. */ @Deprecated public static final int tls1_3 = SocketBase.SSL_LIBRARY_VERSION_TLS_1_3; public SSLVersionRange(SSLVersion minVersion, SSLVersion maxVersion) throws IllegalArgumentException { if (minVersion.value() > maxVersion.value()) { throw new IllegalArgumentException("Arguments out of range"); } this.minVersion = minVersion; this.maxVersion = maxVersion; } /** * Used by the C code, do not use it directly * @deprecated Replaced with SSLVersionRange(SSLVersion minVersion, SSLVersion maxVersion). * @param min_enum * @param max_enum * @throws IllegalArgumentException */ @Deprecated public SSLVersionRange(int min_enum, int max_enum) throws IllegalArgumentException { this(SSLVersion.valueOf(min_enum), SSLVersion.valueOf(max_enum)); } public SSLVersion getMinVersion() { return minVersion; } public SSLVersion getMaxVersion() { return maxVersion; } /** * @return enumeration value */ public int getMinEnum() { return minVersion.value(); } /** * @return enumeration value */ public int getMaxEnum() { return maxVersion.value(); } /** * Gets all of the SSLVersions in this range, including endpoints. * * @return All SSLVersions in this range */ public SSLVersion[] getAllInRange() { ArrayList result = new ArrayList(); for (SSLVersion v : SSLVersion.values()) { if (v.compareTo(this.minVersion) >= 0 && v.compareTo(this.maxVersion) <= 0) { result.add(v); } } return result.toArray(new SSLVersion[result.size()]); } /** * Bounds this SSLVersionRange by the given range. * * The resulting SSLVersionRange does not has a minimum less than * that of its bound and does not have a maximum greater than that * of its bound. */ public SSLVersionRange boundBy(SSLVersionRange bound) { SSLVersion minimum = minVersion; SSLVersion maximum = maxVersion; if (minimum.compareTo(bound.getMinVersion()) < 0) { minimum = bound.getMinVersion(); } if (maximum.compareTo(bound.getMaxVersion()) > 0) { maximum = bound.getMaxVersion(); } return new SSLVersionRange(minimum, maximum); } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SocketBase.java000066400000000000000000000410241412550063600234760ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.ssl; import java.io.IOException; import java.lang.reflect.Constructor; import java.net.Inet6Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.net.UnknownHostException; import java.util.Enumeration; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.crypto.ObjectNotFoundException; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.crypto.X509Certificate; class SocketBase { // This is just another reference to the same proxy object // that is held by the SSLSocket or SSLServerSocket. private SocketProxy sockProxy; private int timeout; int getTimeout() { return timeout; } void setTimeout(int timeout) { this.timeout = timeout; } void setProxy(SocketProxy sockProxy) { this.sockProxy = sockProxy; } native byte[] socketCreate(Object socketObject, SSLCertificateApprovalCallback certApprovalCallback, SSLClientCertificateSelectionCallback clientCertSelectionCallback, java.net.Socket javaSock, String host, int family) throws SocketException; byte[] socketCreate(Object socketObject, SSLCertificateApprovalCallback certApprovalCallback, SSLClientCertificateSelectionCallback clientCertSelectionCallback, int family) throws SocketException { return socketCreate(socketObject, certApprovalCallback, clientCertSelectionCallback, null, null, family); } native void socketBind(byte[] addrBA, int port) throws SocketException; /** * Enums. These must match the enums table in common.c. This is * safer than copying the values of the C constants, which are subject * to change, into Java code. * Note to developer these constants are not all related! i.e. you cannot * pass in PR_SHUTDOWN_RCV to setSSLOption etc! Check their usage * in NSS and NSPR before using. */ static final int SSL_ENABLE_SSL2 = 0; static final int SSL_ENABLE_SSL3 = 1; static final int SSL_ENABLE_TLS = 2; static final int TCP_NODELAY = 3; static final int SO_KEEPALIVE = 4; static final int PR_SHUTDOWN_RCV = 5; static final int PR_SHUTDOWN_SEND = 6; static final int SSL_REQUIRE_CERTIFICATE = 7; static final int SSL_REQUEST_CERTIFICATE = 8; static final int SSL_NO_CACHE = 9; static final int SSL_POLICY_DOMESTIC = 10; static final int SSL_POLICY_EXPORT = 11; static final int SSL_POLICY_FRANCE = 12; static final int SSL_ROLLBACK_DETECTION = 13; static final int SSL_NO_STEP_DOWN = 14; static final int SSL_ENABLE_FDX = 15; static final int SSL_V2_COMPATIBLE_HELLO = 16; static final int SSL_REQUIRE_NEVER = 17; static final int SSL_REQUIRE_ALWAYS = 18; static final int SSL_REQUIRE_FIRST_HANDSHAKE = 19; static final int SSL_REQUIRE_NO_ERROR = 20; static final int SSL_ENABLE_SESSION_TICKETS = 21; static final int SSL_ENABLE_RENEGOTIATION = 22; static final int SSL_RENEGOTIATE_NEVER = 23; static final int SSL_RENEGOTIATE_UNRESTRICTED = 24; static final int SSL_RENEGOTIATE_REQUIRES_XTN = 25; static final int SSL_RENEGOTIATE_TRANSITIONAL = 26; static final int SSL_REQUIRE_SAFE_NEGOTIATION = 27; /* ssl/sslproto.h for supporting SSLVersionRange */ static final int SSL_LIBRARY_VERSION_2 = 28; static final int SSL_LIBRARY_VERSION_3_0 = 29; static final int SSL_LIBRARY_VERSION_TLS_1_0 = 30; static final int SSL_LIBRARY_VERSION_TLS_1_1 = 31; static final int SSL_LIBRARY_VERSION_TLS_1_2 = 32; static final int SSL_LIBRARY_VERSION_TLS_1_3 = 35; /* ssl/sslt.h */ static final int SSL_Variant_Stream = 33; static final int SSL_Variant_Datagram = 34; static final int SSL_ENABLE_POST_HANDSHAKE_AUTH = 36; static final int SSL_AF_INET = 50; static final int SSL_AF_INET6 = 51; void close() throws IOException { try { sockProxy.close(); } catch (Exception e) { String msg = "Unexpected exception while trying to finalize "; msg += "SocketProxy: " + e.getMessage(); throw new IOException(msg, e); } finally { sockProxy = null; } } private boolean requestingClientAuth = false; void requestClientAuth(boolean b) throws SocketException { requestingClientAuth = b; setSSLOption(SSL_REQUEST_CERTIFICATE, b); } public void requestClientAuthNoExpiryCheck(boolean b) throws SocketException { requestingClientAuth = b; requestClientAuthNoExpiryCheckNative(b); } private native void requestClientAuthNoExpiryCheckNative(boolean b) throws SocketException; void enableSSL2(boolean enable) throws SocketException { setSSLOption(SSL_ENABLE_SSL2, enable); } void enableSSL3(boolean enable) throws SocketException { setSSLOption(SSL_ENABLE_SSL3, enable); } void enableTLS(boolean enable) throws SocketException { setSSLOption(SSL_ENABLE_TLS, enable); } void enableSessionTickets(boolean enable) throws SocketException { setSSLOption(SSL_ENABLE_SESSION_TICKETS, enable); } void enableRenegotiation(int mode) throws SocketException { setSSLOptionMode(SocketBase.SSL_ENABLE_RENEGOTIATION, mode); } void enableRequireSafeNegotiation(boolean enable) throws SocketException { setSSLOption(SSL_REQUIRE_SAFE_NEGOTIATION, enable); } void enableRollbackDetection(boolean enable) throws SocketException { setSSLOption(SSL_ROLLBACK_DETECTION, enable); } void enableStepDown(boolean enable) throws SocketException { setSSLOption(SSL_NO_STEP_DOWN, enable); } void enableFDX(boolean enable) throws SocketException { setSSLOption(SSL_ENABLE_FDX, enable); } void enableV2CompatibleHello(boolean enable) throws SocketException { setSSLOption(SSL_V2_COMPATIBLE_HELLO, enable); } void enablePostHandshakeAuth(boolean enable) throws SocketException { setSSLOption(SSL_ENABLE_POST_HANDSHAKE_AUTH, enable); } void setSSLOption(int option, boolean on) throws SocketException { setSSLOption(option, on ? 1 : 0); } /** * Sets SSL options for this socket that have simple * enable/disable values. */ native void setSSLOption(int option, int on) throws SocketException; void setSSLVersionRange(SSLVersionRange range) throws SocketException { setSSLVersionRange(range.getMinVersion().value(), range.getMaxVersion().value()); } /** * Sets SSL Version Range for this socket to support TLS v1.1 to v1.3 */ native void setSSLVersionRange(int min, int max) throws SocketException; /** * Sets the SSL option setting mode value use for options * that have more values than just enable/disable. */ native void setSSLOptionMode(int option, int option2) throws SocketException; /* return 0 for option disabled 1 for option enabled. */ native int getSSLOption(int option) throws SocketException; public String getSSLOptions() { StringBuffer buf = new StringBuffer(); try { buf.append("SSL Options configured for this SSLSocket:"); buf.append("\nSSL_ENABLE_SSL2" + ((getSSLOption(SocketBase.SSL_ENABLE_SSL2) != 0) ? "=on" : "=off")); buf.append("\nSSL_ENABLE_SSL3" + ((getSSLOption(SocketBase.SSL_ENABLE_SSL3) != 0) ? "=on" : "=off")); buf.append("\nSSL_ENABLE_TLS" + ((getSSLOption(SocketBase.SSL_ENABLE_TLS) != 0) ? "=on" : "=off")); buf.append("\nSSL_REQUIRE_CERTIFICATE"); switch (getSSLOption(SocketBase.SSL_REQUIRE_CERTIFICATE)) { case 0: buf.append("=Never"); break; case 1: buf.append("=Always"); break; case 2: buf.append("=First Handshake"); break; case 3: buf.append("=No Error"); break; default: buf.append("=Report JSS Bug this option has a status."); break; } //end switch buf.append("\nSSL_REQUEST_CERTIFICATE" + ((getSSLOption(SocketBase.SSL_REQUEST_CERTIFICATE) != 0) ? "=on" : "=off")); buf.append("\nSSL_NO_CACHE" + ((getSSLOption(SocketBase.SSL_NO_CACHE) != 0) ? "=on" : "=off")); buf.append("\nSSL_ROLLBACK_DETECTION" + ((getSSLOption(SocketBase.SSL_ROLLBACK_DETECTION) != 0) ? "=on" : "=off")); buf.append("\nSSL_NO_STEP_DOWN" + ((getSSLOption(SocketBase.SSL_NO_STEP_DOWN) != 0) ? "=on" : "=off")); buf.append("\nSSL_ENABLE_FDX" + ((getSSLOption(SocketBase.SSL_ENABLE_FDX) != 0) ? "=on" : "=off")); buf.append("\nSSL_V2_COMPATIBLE_HELLO" + ((getSSLOption(SocketBase.SSL_V2_COMPATIBLE_HELLO) != 0) ? "=on" : "=off")); buf.append("\nSSL_ENABLE_SESSION_TICKETS" + ((getSSLOption(SocketBase.SSL_ENABLE_SESSION_TICKETS) != 0) ? "=on" : "=off")); buf.append("\nSSL_ENABLE_RENEGOTIATION"); switch (getSSLOption(SocketBase.SSL_ENABLE_RENEGOTIATION)) { case 0: buf.append("=SSL_RENEGOTIATE_NEVER"); break; case 1: buf.append("=SSL_RENEGOTIATE_UNRESTRICTED"); break; case 2: buf.append("=SSL_RENEGOTIATE_REQUIRES_XTN"); break; case 3: buf.append("=SSL_RENEGOTIATE_TRANSITIONAL"); break; default: buf.append("=Report JSS Bug this option has a status."); break; } //end switch buf.append("\nSSL_REQUIRE_SAFE_NEGOTIATION" + ((getSSLOption(SocketBase.SSL_REQUIRE_SAFE_NEGOTIATION) != 0) ? "=on" : "=off")); } catch (SocketException e) { buf.append("\ngetSSLOptions exception " + e.getMessage()); } return buf.toString(); } /** * Converts a host-ordered 4-byte internet address into an InetAddress. * Unfortunately InetAddress provides no more efficient means * of construction than getByName(), and it is final. * * @return The InetAddress corresponding to the given integer, * or null if the InetAddress could not be constructed. */ private static InetAddress convertIntToInetAddress(int intAddr) { InetAddress in; int[] addr = new int[4]; addr[0] = ((intAddr >>> 24) & 0xff); addr[1] = ((intAddr >>> 16) & 0xff); addr[2] = ((intAddr >>> 8) & 0xff); addr[3] = ((intAddr) & 0xff); try { in = InetAddress.getByName( addr[0] + "." + addr[1] + "." + addr[2] + "." + addr[3]); } catch (java.net.UnknownHostException e) { in = null; } return in; } private native byte[] getLocalAddressByteArrayNative() throws SocketException; private native byte[] getPeerAddressByteArrayNative() throws SocketException; /** * @return the InetAddress of the peer end of the socket. */ InetAddress getInetAddress() { try { byte[] address = getPeerAddressByteArrayNative(); InetAddress iAddr = null; try { iAddr = InetAddress.getByAddress(address); } catch (UnknownHostException e) { } return iAddr; } catch (SocketException e) { return null; } } private native int getPeerAddressNative() throws SocketException; /** * @return The local IP address. */ InetAddress getLocalAddress() { try { byte[] address = getLocalAddressByteArrayNative(); InetAddress lAddr = null; try { lAddr = InetAddress.getByAddress(address); } catch (UnknownHostException e) { } return lAddr; } catch (SocketException e) { return null; } } private native int getLocalAddressNative() throws SocketException; public int getLocalPort() { try { return getLocalPortNative(); } catch (SocketException e) { return 0; } } private native int getLocalPortNative() throws SocketException; void requireClientAuth(boolean require, boolean onRedo) throws SocketException { if (require && !requestingClientAuth) { requestClientAuth(true); } setSSLOption(SSL_REQUIRE_CERTIFICATE, require ? (onRedo ? 1 : 2) : 0); } void requireClientAuth(int mode) throws SocketException { if (mode > 0 && !requestingClientAuth) { requestClientAuth(true); } setSSLOptionMode(SocketBase.SSL_REQUIRE_CERTIFICATE, mode); } /** * Sets the nickname of the certificate to use for client authentication. */ public void setClientCertNickname(String nick) throws SocketException { try { CryptoManager cm = CryptoManager.getInstance(); X509Certificate cert = cm.findCertByNickname(nick); setClientCert(cert); } catch (NotInitializedException nie) { throw new RuntimeException(nie); } catch (ObjectNotFoundException onfe) { throw new RuntimeException(onfe); } catch (TokenException te) { throw new RuntimeException(te); } } native void setClientCert(org.mozilla.jss.crypto.X509Certificate cert) throws SocketException; void useCache(boolean b) throws SocketException { setSSLOption(SSL_NO_CACHE, !b); } static Throwable processExceptions(Throwable topException, Throwable bottomException) { try { StringBuffer strBuf; strBuf = new StringBuffer(topException.toString()); if (bottomException != null) { strBuf.append(" --> "); strBuf.append(bottomException.toString()); } Class excepClass = topException.getClass(); Class stringClass = java.lang.String.class; Constructor cons = excepClass.getConstructor(new Class[] { stringClass }); return (Throwable) cons.newInstance(new Object[] { strBuf.toString() }); } catch (Exception e) { throw new RuntimeException("Problem constructing exception container: " + e.getMessage(), e); //return topException; } } static private int supportsIPV6 = -1; static boolean supportsIPV6() { if (supportsIPV6 >= 0) { if (supportsIPV6 > 0) { return true; } else { return false; } } Enumeration netInter; try { netInter = NetworkInterface.getNetworkInterfaces(); } catch (SocketException e) { return false; } if (netInter == null) { return false; } while (netInter.hasMoreElements()) { NetworkInterface ni = netInter.nextElement(); Enumeration addrs = ni.getInetAddresses(); while (addrs.hasMoreElements()) { InetAddress o = addrs.nextElement(); if (o.getClass() == Inet6Address.class) { supportsIPV6 = 1; return true; } } } supportsIPV6 = 0; return false; } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/SocketProxy.java000066400000000000000000000010261412550063600237430ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.ssl; class SocketProxy extends org.mozilla.jss.util.NativeProxy { public SocketProxy(byte[] pointer) { super(pointer); } @Override protected native void releaseNativeResources(); @Override protected void finalize() throws Throwable { super.finalize(); } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/TestCertApprovalCallback.java000066400000000000000000000054051412550063600263350ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.ssl; import java.util.Enumeration; import org.mozilla.jss.crypto.InternalCertificate; /** * This is a test implementation of the certificate approval callback which * gets invoked when the server presents a certificate which is not * trusted by the client */ public class TestCertApprovalCallback implements SSLCertificateApprovalCallback { @Override public boolean approve( org.mozilla.jss.crypto.X509Certificate servercert, SSLCertificateApprovalCallback.ValidityStatus status) { SSLCertificateApprovalCallback.ValidityItem item; System.out.println("in TestCertApprovalCallback.approve()"); /* dump out server cert details */ System.out.println("Peer cert details: " + "\n subject: " + servercert.getSubjectDN().toString() + "\n issuer: " + servercert.getIssuerDN().toString() + "\n serial: " + servercert.getSerialNumber().toString()); /* iterate through all the problems */ boolean trust_the_server_cert = false; Enumeration errors = status.getReasons(); int i = 0; while (errors.hasMoreElements()) { i++; item = errors.nextElement(); System.out.println("item " + i + " reason=" + item.getReason() + " depth=" + item.getDepth()); org.mozilla.jss.crypto.X509Certificate cert = item.getCert(); if (item.getReason() == SSLCertificateApprovalCallback.ValidityStatus.UNTRUSTED_ISSUER) { trust_the_server_cert = true; } System.out.println(" cert details: " + "\n subject: " + cert.getSubjectDN().toString() + "\n issuer: " + cert.getIssuerDN().toString() + "\n serial: " + cert.getSerialNumber().toString()); } if (trust_the_server_cert) { System.out.println("importing certificate."); try { InternalCertificate newcert = org.mozilla.jss.CryptoManager.getInstance().importCertToPerm(servercert, "testnick"); newcert.setSSLTrust(InternalCertificate.TRUSTED_PEER | InternalCertificate.VALID_PEER); } catch (Exception e) { System.out.println("thrown exception: " + e); } } /* allow the connection to continue. returning false here would abort the connection */ return true; } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/TestClientCertificateSelectionCallback.java000066400000000000000000000036121412550063600311600ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.ssl; import java.util.Enumeration; import java.util.Vector; /** * This interface is what you should implement if you want to * be able to decide whether or not you want to approve the peer's cert, * instead of having NSS do that. */ public class TestClientCertificateSelectionCallback implements SSLClientCertificateSelectionCallback { /** * this method will be called form the native callback code * when a certificate is requested. You must return a String * which is the nickname of the certificate you wish to present. * * @param nicknames A Vector of Strings. These strings are an * aid to the user to select the correct nickname. This list is * made from the list of all certs which are valid, match the * CA's trusted by the server, and which you have the private * key of. If nicknames.length is 0, you should present an * error to the user saying 'you do not have any unexpired * certificates'. * @return You must return the nickname of the certificate you * wish to use. You can return null if you do not wish to send * a certificate. */ @Override public String select(Vector nicknames) { Enumeration e = nicknames.elements(); String s = "", first = null; System.out.println("in TestClientCertificateSelectionCallback.select() " + s); while (e.hasMoreElements()) { s = e.nextElement(); if (first == null) { first = s; } System.out.println(" " + s); } return first; } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/callbacks.c000066400000000000000000000604631412550063600227030ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include #include #include #include "jssl.h" #include #include #include #include int JSSL_getOCSPPolicy() { JNIEnv *env; jint policy = -1; jmethodID getOCSPPolicyID; jclass cryptoManagerClass; /* get the JNI environment */ if((*JSS_javaVM)->AttachCurrentThread(JSS_javaVM, (void**)&env, NULL) != 0){ PR_ASSERT(PR_FALSE); goto finish; } cryptoManagerClass = (*env)->FindClass(env, CRYPTO_MANAGER_NAME); if( cryptoManagerClass == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } getOCSPPolicyID = (*env)->GetStaticMethodID(env, cryptoManagerClass, GET_OCSP_POLICY_NAME,GET_OCSP_POLICY_SIG); if( getOCSPPolicyID == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } policy = (*env)->CallStaticIntMethod(env, cryptoManagerClass, getOCSPPolicyID); finish: return (int) policy; } static SECStatus secCmpCertChainWCANames(CERTCertificate *cert, CERTDistNames *caNames) { SECItem * caname; CERTCertificate * curcert; CERTCertificate * oldcert; PRUint32 contentlen; int j; int headerlen; int depth; SECStatus rv; SECItem issuerName; SECItem compatIssuerName; depth=0; curcert = CERT_DupCertificate(cert); while( curcert ) { issuerName = curcert->derIssuer; /* compute an alternate issuer name for compatibility with 2.0 * enterprise server, which send the CA names without * the outer layer of DER header */ rv = DER_Lengths(&issuerName, &headerlen, &contentlen); if ( rv == SECSuccess ) { compatIssuerName.data = &issuerName.data[headerlen]; compatIssuerName.len = issuerName.len - headerlen; } else { compatIssuerName.data = NULL; compatIssuerName.len = 0; } for (j = 0; j < caNames->nnames; j++) { caname = &caNames->names[j]; if (SECITEM_CompareItem(&issuerName, caname) == SECEqual) { rv = SECSuccess; CERT_DestroyCertificate(curcert); goto done; } else if (SECITEM_CompareItem(&compatIssuerName, caname) == SECEqual) { rv = SECSuccess; CERT_DestroyCertificate(curcert); goto done; } } if ( ( depth <= 20 ) && ( SECITEM_CompareItem(&curcert->derIssuer, &curcert->derSubject) != SECEqual ) ) { oldcert = curcert; curcert = CERT_FindCertByName(curcert->dbhandle, &curcert->derIssuer); CERT_DestroyCertificate(oldcert); depth++; } else { CERT_DestroyCertificate(curcert); curcert = NULL; } } rv = SECFailure; done: return rv; } /* * This callback is called when the peer has request you to send you * client-auth certificate. You get to pick which one you want * to send. * * Expected return values: * 0 SECSuccess * -1 SECFailure - No suitable certificate found. * -2 SECWouldBlock (we're waiting while we ask the user). */ SECStatus JSSL_CallCertSelectionCallback( void * arg, PRFileDesc * fd, CERTDistNames * caNames, CERTCertificate ** pRetCert, SECKEYPrivateKey ** pRetKey) { CERTCertificate * cert; PK11SlotInfo * slot; SECKEYPrivateKey * privkey; jobject nicknamecallback = (jobject)arg; SECStatus rv = SECFailure; CERTCertNicknames * names; int i; int count =0; jclass vectorclass; jmethodID vectorcons; jobject vector; jmethodID vector_add; jstring nickname_string; jstring chosen_nickname; const char *chosen_nickname_for_c; jclass clientcertselectionclass; jmethodID clientcertselectionclass_select; JNIEnv *env; int debug_cc=0; if((*JSS_javaVM)->AttachCurrentThread(JSS_javaVM, (void**)&env, NULL) != 0){ PR_ASSERT(PR_FALSE); return SECFailure; } PR_ASSERT(env != NULL); clientcertselectionclass = (*env)->GetObjectClass(env,nicknamecallback); clientcertselectionclass_select = (*env)->GetMethodID( env, clientcertselectionclass, "select", "(Ljava/util/Vector;)Ljava/lang/String;" ); /* get java bits and piece ready to create a new vector */ vectorclass = (*env)->FindClass( env, "java/util/Vector"); if (debug_cc) { PR_fprintf(PR_STDOUT," got vectorclass: %lx\n",vectorclass); } vectorcons = (*env)->GetMethodID( env, vectorclass,"","()V"); if (debug_cc) { PR_fprintf(PR_STDOUT," got vectorcons: %lx\n",vectorcons); } vector_add = (*env)->GetMethodID( env, vectorclass, "addElement", "(Ljava/lang/Object;)V"); if (debug_cc) { PR_fprintf(PR_STDOUT," got vectoradd: %lx\n",vector_add); } /* create new vector */ vector = (*env)->NewObject( env, vectorclass, vectorcons); if (debug_cc) { PR_fprintf(PR_STDOUT," got new vector: %lx\n",vector); } /* next, get a list of all the valid nicknames */ names = CERT_GetCertNicknames(CERT_GetDefaultCertDB(), SEC_CERT_NICKNAMES_USER, NULL /*pinarg*/); if (names != NULL) { for (i = 0; i < names->numnicknames; i++) { if (debug_cc) { PR_fprintf(PR_STDOUT,"checking nn: %s\n",names->nicknames[i]); } cert = JSS_PK11_findCertAndSlotFromNickname( names->nicknames[i], NULL /*pinarg*/, &slot); if ( !cert ) continue; /* Only check unexpired certs */ if ( CERT_CheckCertValidTimes(cert, PR_Now(), PR_TRUE /*allowOverride*/) != secCertTimeValid ) { if (debug_cc) { PR_fprintf(PR_STDOUT," not valid\n"); } CERT_DestroyCertificate(cert); PK11_FreeSlot(slot); continue; } rv = secCmpCertChainWCANames(cert, caNames); if ( rv == SECSuccess ) { if (debug_cc) { PR_fprintf(PR_STDOUT," matches ca name\n"); } privkey = PK11_FindPrivateKeyFromCert(slot, cert, NULL /*pinarg*/); /* just test if we have the private key */ if ( privkey ) { count++; if (debug_cc) { PR_fprintf(PR_STDOUT," found privkey\n"); } SECKEY_DestroyPrivateKey(privkey); /* if we have, then this nickname has passed all the tests necessary to put it in the list */ nickname_string = (*env)->NewStringUTF(env, names->nicknames[i]); if (debug_cc) { PR_fprintf(PR_STDOUT," calling vector_add\n"); } (*env)->CallVoidMethod(env,vector,vector_add, nickname_string ); if (debug_cc) { PR_fprintf(PR_STDOUT," back from vector_add\n"); } } } CERT_DestroyCertificate(cert); PK11_FreeSlot(slot); } CERT_FreeNicknames(names); } /* okay - so we made a vector of the certs - now call the java class to figure out which one to send */ chosen_nickname = (*env)->CallObjectMethod(env,nicknamecallback, clientcertselectionclass_select, vector ); chosen_nickname_for_c = JSS_RefJString(env, chosen_nickname); if (chosen_nickname_for_c == NULL) { return SECFailure; } if (debug_cc) { PR_fprintf(PR_STDOUT," chosen nickname: %s\n",chosen_nickname_for_c); } cert = JSS_PK11_findCertAndSlotFromNickname(chosen_nickname_for_c, NULL /*pinarg*/, &slot); if (debug_cc) { PR_fprintf(PR_STDOUT," found certificate\n"); } JSS_DerefJString(env, chosen_nickname, chosen_nickname_for_c); if (cert == NULL) { return SECFailure; } privkey = PK11_FindPrivateKeyFromCert(slot, cert, NULL /*pinarg*/); PK11_FreeSlot(slot); if ( privkey == NULL ) { CERT_DestroyCertificate(cert); return SECFailure; } if (debug_cc) { PR_fprintf(PR_STDOUT," found privkey. returning\n"); } *pRetCert = cert; *pRetKey = privkey; rv = SECSuccess; return rv; } void JSSL_AlertReceivedCallback(const PRFileDesc *fd, void *arg, const SSLAlert *alert) { JSSL_SocketData *socket = (JSSL_SocketData*) arg; jint rc; JNIEnv *env; jclass socketClass, eventClass; jmethodID eventConstructor; jobject event; jmethodID fireEvent; PR_ASSERT(socket != NULL); PR_ASSERT(socket->socketObject != NULL); rc = (*JSS_javaVM)->AttachCurrentThread(JSS_javaVM, (void**)&env, NULL); PR_ASSERT(rc == JNI_OK); PR_ASSERT(env != NULL); /* Fast return when assumptions are incorrect. */ if (socket == NULL || socket->socketObject == NULL || rc != JNI_OK || env == NULL) { return; } /* SSLAlertEvent event = new SSLAlertEvent(socket); */ socketClass = (*env)->FindClass(env, SSLSOCKET_CLASS); PR_ASSERT(socketClass != NULL); eventClass = (*env)->FindClass(env, SSL_ALERT_EVENT_CLASS); PR_ASSERT(eventClass != NULL); eventConstructor = (*env)->GetMethodID(env, eventClass, "", "(L" SSLSOCKET_CLASS ";II)V"); PR_ASSERT(eventConstructor != NULL); event = (*env)->NewObject(env, eventClass, eventConstructor, socket->socketObject, (int)alert->level, (int)alert->description); PR_ASSERT(event != NULL); /* socket.fireAlertReceivedEvent(event); */ fireEvent = (*env)->GetMethodID(env, socketClass, "fireAlertReceivedEvent", "(L" SSL_ALERT_EVENT_CLASS ";)V"); PR_ASSERT(fireEvent != NULL); (*env)->CallVoidMethod(env, socket->socketObject, fireEvent, event); (*JSS_javaVM)->DetachCurrentThread(JSS_javaVM); } void JSSL_AlertSentCallback(const PRFileDesc *fd, void *arg, const SSLAlert *alert) { JSSL_SocketData *socket = (JSSL_SocketData*) arg; jint rc; JNIEnv *env; jclass socketClass, eventClass; jmethodID eventConstructor, eventSetLevel, eventSetDescription; jobject event; jmethodID fireEvent; PR_ASSERT(socket != NULL); PR_ASSERT(socket->socketObject != NULL); rc = (*JSS_javaVM)->AttachCurrentThread(JSS_javaVM, (void**)&env, NULL); PR_ASSERT(rc == JNI_OK); PR_ASSERT(env != NULL); /* Fast return when assumptions are incorrect. */ if (socket == NULL || socket->socketObject == NULL || rc != JNI_OK || env == NULL) { return; } /* SSLAlertEvent event = new SSLAlertEvent(socket); */ socketClass = (*env)->FindClass(env, SSLSOCKET_CLASS); PR_ASSERT(socketClass != NULL); eventClass = (*env)->FindClass(env, SSL_ALERT_EVENT_CLASS); PR_ASSERT(eventClass != NULL); eventConstructor = (*env)->GetMethodID(env, eventClass, "", "(L" SSLSOCKET_CLASS ";)V"); PR_ASSERT(eventConstructor != NULL); event = (*env)->NewObject(env, eventClass, eventConstructor, socket->socketObject); PR_ASSERT(event != NULL); /* event.setLevel(level); */ eventSetLevel = (*env)->GetMethodID(env, eventClass, "setLevel", "(I)V"); PR_ASSERT(eventSetLevel != NULL); (*env)->CallVoidMethod(env, event, eventSetLevel, (int)alert->level); /* event.setDescription(description); */ eventSetDescription = (*env)->GetMethodID(env, eventClass, "setDescription", "(I)V"); PR_ASSERT(eventSetDescription != NULL); (*env)->CallVoidMethod(env, event, eventSetDescription, alert->description); /* socket.fireAlertSentEvent(event); */ fireEvent = (*env)->GetMethodID(env, socketClass, "fireAlertSentEvent", "(L" SSL_ALERT_EVENT_CLASS ";)V"); PR_ASSERT(fireEvent != NULL); (*env)->CallVoidMethod(env, socket->socketObject, fireEvent, event); (*JSS_javaVM)->DetachCurrentThread(JSS_javaVM); } void JSSL_HandshakeCallback(PRFileDesc *fd, void *arg) { JSSL_SocketData *sock = (JSSL_SocketData*) arg; jclass sockClass; jmethodID notifierID; JNIEnv *env; PR_ASSERT(sock!=NULL); /* get the JNI environment */ if((*JSS_javaVM)->AttachCurrentThread(JSS_javaVM, (void**)&env, NULL) != 0){ PR_ASSERT(PR_FALSE); goto finish; } PR_ASSERT(env != NULL); /* get the handshake notification method ID */ PR_ASSERT(sock->socketObject!=NULL); sockClass = (*env)->GetObjectClass(env, sock->socketObject); notifierID = (*env)->GetMethodID(env, sockClass, SSLSOCKET_HANDSHAKE_NOTIFIER_NAME, SSLSOCKET_HANDSHAKE_NOTIFIER_SIG); if(notifierID == NULL) goto finish; /* call the handshake notification method */ (*env)->CallVoidMethod(env, sock->socketObject, notifierID); finish: return; } /* * Callback from SSL for checking certificate the peer (other end of * the socket) presents. */ SECStatus JSSL_DefaultCertAuthCallback(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer) { char * hostname = NULL; SECStatus rv = SECFailure; SECCertUsage certUsage; CERTCertificate *peerCert=NULL; int ocspPolicy = JSSL_getOCSPPolicy(); certUsage = isServer ? certUsageSSLClient : certUsageSSLServer; /* PKIX call needs a SECCertificate usage, convert */ SECCertificateUsage certificateUsage = (SECCertificateUsage)1 << certUsage; /* SSL_PeerCertificate() returns a shallow copy of the cert, so we must destroy it before we exit this function */ peerCert = SSL_PeerCertificate(fd); if (peerCert) { if( ocspPolicy == OCSP_LEAF_AND_CHAIN_POLICY) { rv = JSSL_verifyCertPKIX( peerCert, certificateUsage, NULL /* pin arg */, ocspPolicy, NULL, NULL); } else { rv = CERT_VerifyCertNow(CERT_GetDefaultCertDB(), peerCert, checkSig, certUsage, NULL /*pinarg*/); } } /* if we're a server, then we don't need to check the CN of the certificate, so we can just return whatever returncode we have now */ if ( rv != SECSuccess || isServer ) { if (peerCert) { CERT_DestroyCertificate(peerCert); } return (int)rv; } /* cert is OK. This is the client side of an SSL connection. * Now check the name field in the cert against the desired hostname. * NB: This is our only defense against Man-In-The-Middle (MITM) attacks! */ hostname = SSL_RevealURL(fd); /* really is a hostname, not a URL */ if (hostname && hostname[0]) { rv = CERT_VerifyCertName(peerCert, hostname); PORT_Free(hostname); } else { rv = SECFailure; } if (rv == SECFailure) { PR_SetError(SSL_ERROR_BAD_CERT_DOMAIN, 0); } if (peerCert) CERT_DestroyCertificate(peerCert); return rv; } static void addToVerifyLog(JNIEnv *env, CERTVerifyLog *log, CERTCertificate *cert, unsigned long error, unsigned int depth) { CERTVerifyLogNode *node, *tnode; PR_ASSERT(log != NULL); PL_ARENA_ALLOCATE(node, log->arena, sizeof(CERTVerifyLogNode)); if ( node == NULL ) { JSS_throw(env, OUT_OF_MEMORY_ERROR); return; } node->cert = CERT_DupCertificate(cert); node->error = error; node->depth = depth; node->arg = NULL; if ( log->tail == NULL ) { /* empty list */ log->head = log->tail = node; node->prev = NULL; node->next = NULL; } else if ( depth >= log->tail->depth ) { /* add to tail */ node->prev = log->tail; log->tail->next = node; log->tail = node; node->next = NULL; } else if ( depth < log->head->depth ) { /* add at head */ node->prev = NULL; node->next = log->head; log->head->prev = node; log->head = node; } else { /* add in middle */ tnode = log->tail; while ( tnode != NULL ) { if ( depth >= tnode->depth ) { /* insert after tnode */ node->prev = tnode; node->next = tnode->next; tnode->next->prev = node; tnode->next = node; break; } tnode = tnode->prev; } } log->count++; } /* * Callback from SSL for checking a (possibly) expired * certificate the peer presents. * * obj - a jobject -> instance of a class implementing * the SSLCertificateApprovalCallback interface */ SECStatus JSSL_JavaCertAuthCallback(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer) { CERTCertificate *peerCert=NULL; CERTVerifyLog log; JNIEnv *env; jobject validityStatus; jmethodID addReasonMethod; int certUsage; int checkcn_rv; jmethodID approveMethod; jboolean result; char *hostname=NULL; SECStatus retval = SECFailure; SECStatus verificationResult; PR_ASSERT(arg != NULL); PR_ASSERT(fd != NULL); /* initialize logging structures */ log.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if( log.arena == NULL ) return SECFailure; log.head = NULL; log.tail = NULL; log.count = 0; int ocspPolicy = JSSL_getOCSPPolicy(); /* get the JNI environment */ if((*JSS_javaVM)->AttachCurrentThread(JSS_javaVM, (void**)&env, NULL) != 0){ PR_ASSERT(PR_FALSE); goto finish; } /* First, get a handle on the cert that the peer presented */ peerCert = SSL_PeerCertificate(fd); /* if peer didn't present a cert, why am I called? */ if (peerCert == NULL) goto finish; certUsage = isServer ? certUsageSSLClient : certUsageSSLServer; /* PKIX call needs a SECCertificate usage, convert */ SECCertificateUsage certificateUsage = (SECCertificateUsage)1 << certUsage; /* * verify it against current time - (can't use * CERT_VerifyCertNow() since it doesn't allow passing of * logging parameter) */ if( ocspPolicy == OCSP_LEAF_AND_CHAIN_POLICY) { verificationResult = JSSL_verifyCertPKIX( peerCert, certificateUsage, NULL /* pin arg */, ocspPolicy, &log, NULL); } else { verificationResult = CERT_VerifyCert( CERT_GetDefaultCertDB(), peerCert, checkSig, certUsage, PR_Now(), NULL /*pinarg*/, &log); } if (verificationResult == SECSuccess && log.count > 0) { verificationResult = SECFailure; } /* * Verify the domain name of the cert. */ hostname = SSL_RevealURL(fd); /* really is a hostname, not a URL */ if (hostname && hostname[0]) { checkcn_rv = CERT_VerifyCertName(peerCert, hostname); PORT_Free(hostname); } else { checkcn_rv = SECFailure; } if (checkcn_rv != SECSuccess) { addToVerifyLog(env, &log,peerCert,SSL_ERROR_BAD_CERT_DOMAIN,0); if((*env)->ExceptionOccurred(env) != NULL) goto finish; verificationResult = SECFailure; } /* * create a new ValidityStatus object */ { jclass clazz; jmethodID cons; clazz = (*env)->FindClass(env, SSLCERT_APP_CB_VALIDITY_STATUS_CLASS); if( clazz == NULL ) goto finish; cons = (*env)->GetMethodID(env, clazz, PLAIN_CONSTRUCTOR, PLAIN_CONSTRUCTOR_SIG); if( cons == NULL ) goto finish; validityStatus = (*env)->NewObject(env, clazz, cons); if( validityStatus == NULL ) { goto finish; } /* get the addReason methodID while we're at it */ addReasonMethod = (*env)->GetMethodID(env, clazz, SSLCERT_APP_CB_VALIDITY_STATUS_ADD_REASON_NAME, SSLCERT_APP_CB_VALIDITY_STATUS_ADD_REASON_SIG); if( addReasonMethod == NULL ) { goto finish; } } /* * Load up the ValidityStatus object with all the reasons for failure */ if (verificationResult == SECFailure) { CERTVerifyLogNode *node; int error; CERTCertificate *errorcert=NULL; int depth; jobject ninjacert; node = log.head; while (node) { error = node->error; errorcert = node->cert; node->cert = NULL; depth = node->depth; ninjacert = JSS_PK11_wrapCert(env,&errorcert); (*env)->CallVoidMethod(env, validityStatus, addReasonMethod, error, ninjacert, depth ); node = node->next; } } /* * Call the approval callback */ { jobject approvalCallbackObj; jclass approvalCallbackClass; jobject peerninjacert; approvalCallbackObj = (jobject) arg; approvalCallbackClass = (*env)->GetObjectClass(env,approvalCallbackObj); approveMethod = (*env)->GetMethodID( env, approvalCallbackClass, SSLCERT_APP_CB_APPROVE_NAME, SSLCERT_APP_CB_APPROVE_SIG); if( approveMethod == NULL ) { PR_ASSERT(PR_FALSE); goto finish; } peerninjacert = JSS_PK11_wrapCert(env,&peerCert); if( peerninjacert == NULL) { PR_ASSERT(PR_FALSE); goto finish; } result = (*env)->CallBooleanMethod(env, approvalCallbackObj, approveMethod, peerninjacert, validityStatus); if( result == JNI_TRUE ) { retval = SECSuccess; } } finish: if( peerCert != NULL ) { CERT_DestroyCertificate(peerCert); } PORT_FreeArena(log.arena, PR_FALSE); return retval; } SECStatus JSSL_GetClientAuthData( void * arg, PRFileDesc * fd, CERTDistNames * caNames, CERTCertificate ** pRetCert, SECKEYPrivateKey ** pRetKey) { SECKEYPrivateKey * privkey; JSSL_SocketData * sock; SECStatus rv = SECFailure; PR_ASSERT(arg != NULL); sock = (JSSL_SocketData*) arg; if (sock->clientCert) { privkey = PK11_FindPrivateKeyFromCert(sock->clientCertSlot, sock->clientCert, NULL /*pinarg*/); if ( privkey ) { rv = SECSuccess; *pRetCert = CERT_DupCertificate(sock->clientCert); *pRetKey = privkey; } } return rv; } /* * Callback from SSL for checking a (possibly) expired * certificate the peer presents. */ SECStatus JSSL_ConfirmExpiredPeerCert(void *arg, PRFileDesc *fd, PRBool checkSig, PRBool isServer) { SECStatus rv=SECFailure; SECCertUsage certUsage; CERTCertificate* peerCert=NULL; int64 notAfter, notBefore; certUsage = isServer ? certUsageSSLClient : certUsageSSLServer; peerCert = SSL_PeerCertificate(fd); if (peerCert) { rv = CERT_GetCertTimes(peerCert, ¬Before, ¬After); if (rv != SECSuccess) goto finish; /* * Verify the certificate based on it's expiry date. This should * always succeed, if the cert is trusted. It doesn't care if * the cert has expired. */ rv = CERT_VerifyCert(CERT_GetDefaultCertDB(), peerCert, checkSig, certUsage, notAfter, NULL /*pinarg*/, NULL /* log */); } if ( rv != SECSuccess ) goto finish; if( ! isServer ) { /* This is the client side of an SSL connection. * Now check the name field in the cert against the desired hostname. * NB: This is our only defense against Man-In-The-Middle (MITM) attacks! */ char* hostname = NULL; hostname = SSL_RevealURL(fd); /* really is a hostname, not a URL */ if (hostname && hostname[0]) { rv = CERT_VerifyCertName(peerCert, hostname); PORT_Free(hostname); } else { rv = SECFailure; } } finish: if (peerCert!=NULL) CERT_DestroyCertificate(peerCert); return rv; } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/common.c000066400000000000000000001025111412550063600222430ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include #include #include "_jni/org_mozilla_jss_ssl_SSLSocket.h" #include "jssl.h" #include "cert.h" #ifdef WIN32 #include #endif #define SSL_AF_INET 50 #define SSL_AF_INET6 51 void JSSL_throwSSLSocketException(JNIEnv *env, char *message) { const char *errStr; PRErrorCode nativeErrcode; char *msg = NULL; int msgLen; jclass excepClass; jmethodID excepCons; jobject excepObj; jstring msgString; jint VARIABLE_MAY_NOT_BE_USED result; /* * get the error code and error string */ nativeErrcode = PR_GetError(); errStr = JSS_strerror(nativeErrcode); if( errStr == NULL ) { errStr = "Unknown error"; } /* * construct the message */ msgLen = strlen(message) + strlen(errStr) + 40; msg = PR_Malloc(msgLen); if( msg == NULL ) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } PR_snprintf(msg, msgLen, "%s: (%ld) %s", message, nativeErrcode, errStr); /* * turn the message into a Java string */ msgString = (*env)->NewStringUTF(env, msg); if( msgString == NULL ) goto finish; /* * Create the exception object. Use java.net.SocketTimeoutException * for timeouts, org.mozilla.jss.ssl.SSLSocketException for everything * else. */ switch (nativeErrcode) { case PR_PENDING_INTERRUPT_ERROR : excepClass = (*env)->FindClass(env, INTERRUPTED_IO_EXCEPTION); break; case PR_IO_ERROR : excepClass = (*env)->FindClass(env, IO_EXCEPTION); break; case PR_IO_TIMEOUT_ERROR : case PR_CONNECT_TIMEOUT_ERROR : excepClass = (*env)->FindClass(env, SOCKET_TIMEOUT_EXCEPTION); break; default : /* for all other PR_ERRORs throw SocketException */ excepClass = (*env)->FindClass(env, SSLSOCKET_EXCEPTION); break; } PR_ASSERT(excepClass != NULL); if( excepClass == NULL ) goto finish; excepCons = (*env)->GetMethodID(env, excepClass, "", "(Ljava/lang/String;)V"); PR_ASSERT( excepCons != NULL ); if( excepCons == NULL ) goto finish; excepObj = (*env)->NewObject(env, excepClass, excepCons, msgString); PR_ASSERT(excepObj != NULL); if( excepObj == NULL ) goto finish; /* * throw the exception */ result = (*env)->Throw(env, excepObj); PR_ASSERT(result == 0); finish: if( msg != NULL ) { PR_Free(msg); } } /* * This is done for regular sockets that we connect() and server sockets, * but not for sockets that come from accept. */ JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_ssl_SocketBase_socketCreate(JNIEnv *env, jobject self, jobject sockObj, jobject certApprovalCallback, jobject clientCertSelectionCallback, jobject javaSock, jstring host,jint family) { jbyteArray sdArray = NULL; JSSL_SocketData *sockdata = NULL; SECStatus status; PRFileDesc *newFD = NULL; PRFileDesc *tmpFD = NULL; PRFilePrivate *priv = NULL; int socketFamily = 0; if (family != SSL_AF_INET6 && family != SSL_AF_INET) { JSSL_throwSSLSocketException(env, "socketCreate() Invalid family!"); goto finish; } if( family == SSL_AF_INET) socketFamily = PR_AF_INET; else socketFamily = PR_AF_INET6; if( javaSock == NULL ) { /* create a TCP socket */ newFD = PR_OpenTCPSocket(socketFamily); if( newFD == NULL ) { JSSL_throwSSLSocketException(env, "PR_NewTCPSocket() returned NULL"); goto finish; } } else { newFD = JSS_SSL_javasockToPRFD(env, javaSock); if( newFD == NULL ) { JSS_throwMsg(env, SOCKET_EXCEPTION, "failed to construct NSPR wrapper around java socket"); goto finish; } priv = newFD->secret; } /* enable SSL on the socket */ tmpFD = SSL_ImportFD(NULL, newFD); if( tmpFD == NULL ) { JSSL_throwSSLSocketException(env, "SSL_ImportFD() returned NULL"); goto finish; } newFD = tmpFD; sockdata = JSSL_CreateSocketData(env, sockObj, newFD, priv); if( sockdata == NULL ) { goto finish; } newFD = NULL; if( host != NULL ) { const char *chars; int retval; PR_ASSERT( javaSock != NULL ); chars = JSS_RefJString(env, host); retval = SSL_SetURL(sockdata->fd, chars); JSS_DerefJString(env, host, chars); if( retval ) { JSSL_throwSSLSocketException(env, "Failed to set SSL domain name"); goto finish; } } status = SSL_OptionSet(sockdata->fd, SSL_SECURITY, PR_TRUE); if( status != SECSuccess ) { JSSL_throwSSLSocketException(env, "Unable to enable SSL security on socket"); goto finish; } /* setup the handshake callback */ status = SSL_HandshakeCallback(sockdata->fd, JSSL_HandshakeCallback, sockdata); if( status != SECSuccess ) { JSSL_throwSSLSocketException(env, "Unable to install handshake callback"); goto finish; } /* setup the cert authentication callback */ if( certApprovalCallback != NULL ) { /* create global reference to the callback object */ sockdata->certApprovalCallback = (*env)->NewGlobalRef(env, certApprovalCallback); if( sockdata->certApprovalCallback == NULL ) goto finish; /* install the Java callback */ status = SSL_AuthCertificateHook( sockdata->fd, JSSL_JavaCertAuthCallback, (void*) sockdata->certApprovalCallback); } else { /* install the default callback */ status = SSL_AuthCertificateHook( sockdata->fd, JSSL_DefaultCertAuthCallback, NULL); } if( status != SECSuccess ) { JSSL_throwSSLSocketException(env, "Unable to install certificate authentication callback"); goto finish; } /* setup the client cert selection callback */ if( clientCertSelectionCallback != NULL ) { /* create a new global ref */ sockdata->clientCertSelectionCallback = (*env)->NewGlobalRef(env, clientCertSelectionCallback); if(sockdata->clientCertSelectionCallback == NULL) goto finish; /* install the Java callback */ status = SSL_GetClientAuthDataHook( sockdata->fd, JSSL_CallCertSelectionCallback, (void*) sockdata->clientCertSelectionCallback); if( status != SECSuccess ) { JSSL_throwSSLSocketException(env, "Unable to install client certificate selection callback"); goto finish; } } /* pass the pointer back to Java */ sdArray = JSS_ptrToByteArray(env, (void*) sockdata); if( sdArray == NULL ) { /* exception was thrown */ goto finish; } finish: if( (*env)->ExceptionOccurred(env) != NULL ) { if( sockdata != NULL ) { JSSL_DestroySocketData(env, sockdata); } if( newFD != NULL ) { PR_Close(newFD); } } else { PR_ASSERT( sdArray != NULL ); } return sdArray; } JSSL_SocketData* JSSL_CreateSocketData(JNIEnv *env, jobject sockObj, PRFileDesc* newFD, PRFilePrivate *priv) { SECStatus status; JSSL_SocketData *sockdata = NULL; /* make a JSSL_SocketData structure */ sockdata = PR_Malloc( sizeof(JSSL_SocketData) ); if( sockdata == NULL ) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } sockdata->fd = newFD; sockdata->socketObject = NULL; sockdata->certApprovalCallback = NULL; sockdata->clientCertSelectionCallback = NULL; sockdata->clientCert = NULL; sockdata->clientCertSlot = NULL; sockdata->jsockPriv = priv; sockdata->lock = NULL; sockdata->reader = NULL; sockdata->writer = NULL; sockdata->accepter = NULL; sockdata->closePending = PR_FALSE; sockdata->lock = PR_NewLock(); if( sockdata->lock == NULL ) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } /* * Make a global ref to the socket. Since it is a weak reference, it will * get garbage collected if this is the only reference that remains. * We do this so that sockets will get closed when they go out of scope * in the Java layer. */ sockdata->socketObject = NEW_WEAK_GLOBAL_REF(env, sockObj); if( sockdata->socketObject == NULL ) goto finish; /* registering alert received callback */ status = SSL_AlertReceivedCallback(sockdata->fd, JSSL_AlertReceivedCallback, sockdata); if (status != SECSuccess) { JSSL_throwSSLSocketException(env, "Unable to install alert received callback"); goto finish; } /* registering alert sent callback */ status = SSL_AlertSentCallback(sockdata->fd, JSSL_AlertSentCallback, sockdata); if (status != SECSuccess) { JSSL_throwSSLSocketException(env, "Unable to install alert sent callback"); goto finish; } finish: if( (*env)->ExceptionOccurred(env) != NULL ) { if( sockdata != NULL ) { JSSL_DestroySocketData(env, sockdata); sockdata = NULL; } } return sockdata; } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SocketProxy_releaseNativeResources (JNIEnv *env, jobject this) { JSSL_SocketData *sockdata; PR_ASSERT(env != NULL && this != NULL); if (JSS_getPtrFromProxy(env, this, (void**)&sockdata) != PR_SUCCESS) { return; } JSSL_DestroySocketData(env, sockdata); } void JSSL_DestroySocketData(JNIEnv *env, JSSL_SocketData *sd) { if (sd == NULL) { return; } if (sd->fd != NULL) { PR_Close(sd->fd); sd->fd = NULL; } if( sd->socketObject != NULL ) { DELETE_WEAK_GLOBAL_REF(env, sd->socketObject ); } if( sd->certApprovalCallback != NULL ) { (*env)->DeleteGlobalRef(env, sd->certApprovalCallback); } if( sd->clientCertSelectionCallback != NULL ) { (*env)->DeleteGlobalRef(env, sd->clientCertSelectionCallback); } if( sd->clientCert != NULL ) { CERT_DestroyCertificate(sd->clientCert); } if( sd->clientCertSlot != NULL ) { PK11_FreeSlot(sd->clientCertSlot); } if( sd->lock != NULL ) { PR_DestroyLock(sd->lock); } memset(sd, 0, sizeof(JSSL_SocketData)); PR_Free(sd); } /* * These must match up with the constants defined in SocketBase.java. * Note to developer these constants are not all related! i.e. you cannot * pass in PR_SHUTDOWN_RCV to setSSLOption etc! Check their usage * in NSS and NSPR before using. */ PRInt32 JSSL_enums[] = { SSL_ENABLE_SSL2, /* 0 */ /* ssl.h */ SSL_ENABLE_SSL3, /* 1 */ /* ssl.h */ SSL_ENABLE_TLS, /* 2 */ /* ssl.h */ PR_SockOpt_NoDelay, /* 3 */ /* prio.h */ PR_SockOpt_Keepalive, /* 4 */ /* prio.h */ PR_SHUTDOWN_RCV, /* 5 */ /* prio.h */ PR_SHUTDOWN_SEND, /* 6 */ /* prio.h */ SSL_REQUIRE_CERTIFICATE, /* 7 */ /* ssl.h */ SSL_REQUEST_CERTIFICATE, /* 8 */ /* ssl.h */ SSL_NO_CACHE, /* 9 */ /* ssl.h */ SSL_POLICY_DOMESTIC, /* 10 */ /* ssl.h */ SSL_POLICY_EXPORT, /* 11 */ /* ssl.h */ SSL_POLICY_FRANCE, /* 12 */ /* ssl.h */ SSL_ROLLBACK_DETECTION, /* 13 */ /* ssl.h */ SSL_NO_STEP_DOWN, /* 14 */ /* ssl.h */ SSL_ENABLE_FDX, /* 15 */ /* ssl.h */ SSL_V2_COMPATIBLE_HELLO, /* 16 */ /* ssl.h */ SSL_REQUIRE_NEVER, /* 17 */ /* ssl.h */ SSL_REQUIRE_ALWAYS, /* 18 */ /* ssl.h */ SSL_REQUIRE_FIRST_HANDSHAKE,/* 19 */ /* ssl.h */ SSL_REQUIRE_NO_ERROR, /* 20 */ /* ssl.h */ SSL_ENABLE_SESSION_TICKETS, /* 21 */ /* ssl.h */ SSL_ENABLE_RENEGOTIATION, /* 22 */ /* ssl.h */ SSL_RENEGOTIATE_NEVER, /* 23 */ /* ssl.h */ SSL_RENEGOTIATE_UNRESTRICTED, /* 24 */ /* ssl.h */ SSL_RENEGOTIATE_REQUIRES_XTN, /* 25 */ /* ssl.h */ SSL_RENEGOTIATE_TRANSITIONAL, /* 26 */ /* ssl.h */ SSL_REQUIRE_SAFE_NEGOTIATION, /* 27 */ /* ssl.h */ SSL_LIBRARY_VERSION_2, /* 28 */ /* sslproto.h */ SSL_LIBRARY_VERSION_3_0, /* 29 */ /* sslproto.h */ SSL_LIBRARY_VERSION_TLS_1_0, /* 30 */ /* sslproto.h */ SSL_LIBRARY_VERSION_TLS_1_1, /* 31 */ /* sslproto.h */ SSL_LIBRARY_VERSION_TLS_1_2, /* 32 */ /* sslproto.h */ ssl_variant_stream, /* 33 */ /* sslt.h */ ssl_variant_datagram, /* 34 */ /* sslt.h */ SSL_LIBRARY_VERSION_TLS_1_3, /* 35 */ /* sslproto.h */ SSL_ENABLE_POST_HANDSHAKE_AUTH, /* 36 */ /* ssl.h */ 0 }; /* * Reverses the above table mapping enum value -> NSS constant. */ int JSSL_enums_reverse(PRInt32 value) { int index = 0; for (index = 0; index < JSSL_enums_size; index++) { if (JSSL_enums[index] == value) { return index; } } return index; } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SocketBase_socketBind (JNIEnv *env, jobject self, jbyteArray addrBA, jint port) { JSSL_SocketData *sock; PRNetAddr addr; jbyte *addrBAelems = NULL; int addrBALen = 0; PRStatus status; jmethodID supportsIPV6ID; jclass socketBaseClass; jboolean supportsIPV6 = 0; if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) { /* exception was thrown */ goto finish; } /* * setup the PRNetAddr structure */ /* * Do we support IPV6? */ socketBaseClass = (*env)->FindClass(env, SOCKET_BASE_NAME); if( socketBaseClass == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } supportsIPV6ID = (*env)->GetStaticMethodID(env, socketBaseClass, SUPPORTS_IPV6_NAME, SUPPORTS_IPV6_SIG); if( supportsIPV6ID == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } supportsIPV6 = (*env)->CallStaticBooleanMethod(env, socketBaseClass, supportsIPV6ID); memset( &addr, 0, sizeof( PRNetAddr )); if (addrBA != NULL) { if (!JSS_RefByteArray(env, addrBA, &addrBAelems, &addrBALen)) { ASSERT_OUTOFMEM(env); goto finish; } if (addrBALen != 4 && addrBALen != 16) { JSS_throwMsgPrErr(env, BIND_EXCEPTION, "Invalid address in bind!"); goto finish; } if( addrBALen == 4) { addr.inet.family = PR_AF_INET; addr.inet.port = PR_htons(port); memcpy(&addr.inet.ip, addrBAelems, 4); if(supportsIPV6) { addr.inet.family = PR_AF_INET6; addr.ipv6.port = PR_htons(port); PR_ConvertIPv4AddrToIPv6(addr.inet.ip,&addr.ipv6.ip); } } else { /* Must be 16 and ipv6 */ if(supportsIPV6) { addr.ipv6.family = PR_AF_INET6; addr.ipv6.port = PR_htons(port); memcpy(&addr.ipv6.ip,addrBAelems, 16); } else { JSS_throwMsgPrErr(env, BIND_EXCEPTION, "Invalid address in bind!"); goto finish; } } } else { if(supportsIPV6) { status = PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET6, port, &addr); } else { status = PR_SetNetAddr(PR_IpAddrAny, PR_AF_INET, port, &addr); } } /* do the bind() call */ status = PR_Bind(sock->fd, &addr); if( status != PR_SUCCESS ) { JSS_throwMsgPrErr(env, BIND_EXCEPTION, "Could not bind to address"); goto finish; } finish: JSS_DerefByteArray(env, addrBA, addrBAelems, JNI_ABORT); } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SocketBase_requestClientAuthNoExpiryCheckNative (JNIEnv *env, jobject self, jboolean b) { JSSL_SocketData *sock = NULL; SECStatus status; if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) goto finish; /* * Set the option on the socket */ status = SSL_OptionSet(sock->fd, SSL_REQUEST_CERTIFICATE, b); if( status != SECSuccess ) { JSSL_throwSSLSocketException(env, "Failed to set REQUEST_CERTIFICATE option on socket"); goto finish; } if(b) { /* * Set the callback function */ status = SSL_AuthCertificateHook(sock->fd, JSSL_ConfirmExpiredPeerCert, NULL /*cx*/); if( status != SECSuccess ) { JSSL_throwSSLSocketException(env, "Failed to set certificate authentication callback"); goto finish; } } finish: EXCEPTION_CHECK(env, sock) return; } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SocketBase_setSSLOption (JNIEnv *env, jobject self, jint option, jint on) { SECStatus status; JSSL_SocketData *sock = NULL; /* get my fd */ if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) { goto finish; } /* set the option */ status = SSL_OptionSet(sock->fd, JSSL_enums[option], on); if( status != SECSuccess ) { JSSL_throwSSLSocketException(env, "SSL_OptionSet failed"); goto finish; } finish: EXCEPTION_CHECK(env, sock) return; } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SocketBase_setSSLOptionMode (JNIEnv *env, jobject self, jint option, jint mode) { SECStatus status; JSSL_SocketData *sock = NULL; /* get my fd */ if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) { goto finish; } /* set the option */ status = SSL_OptionSet(sock->fd, JSSL_enums[option], JSSL_enums[mode]); if( status != SECSuccess ) { JSSL_throwSSLSocketException(env, "SSL_OptionSet failed"); goto finish; } finish: EXCEPTION_CHECK(env, sock) return; } JNIEXPORT jint JNICALL Java_org_mozilla_jss_ssl_SocketBase_getSSLOption(JNIEnv *env, jobject self, jint option) { JSSL_SocketData *sock = NULL; SECStatus status = SECSuccess; PRBool bOption = PR_FALSE; if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) { goto finish; } /* get the option */ status = SSL_OptionGet(sock->fd, JSSL_enums[option], &bOption); if( status != SECSuccess ) { JSSL_throwSSLSocketException(env, "SSL_OptionGet failed"); goto finish; } finish: EXCEPTION_CHECK(env, sock) return bOption; } PRStatus JSSL_getSockAddr (JNIEnv *env, jobject self, PRNetAddr *addr, LocalOrPeer localOrPeer) { JSSL_SocketData *sock = NULL; PRStatus status=PR_FAILURE; /* get my fd */ if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) { goto finish; } /* get the port */ if( localOrPeer == LOCAL_SOCK ) { status = PR_GetSockName(sock->fd, addr); } else { PR_ASSERT( localOrPeer == PEER_SOCK ); status = PR_GetPeerName(sock->fd, addr); } if( status != PR_SUCCESS ) { JSSL_throwSSLSocketException(env, "PR_GetSockName failed"); } finish: EXCEPTION_CHECK(env, sock) return status; } JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_ssl_SocketBase_getPeerAddressByteArrayNative (JNIEnv *env, jobject self) { jbyteArray byteArray=NULL; PRNetAddr addr; jbyte *address=NULL; int size=4; if( JSSL_getSockAddr(env, self, &addr, PEER_SOCK) != PR_SUCCESS) { goto finish; } if( PR_NetAddrFamily(&addr) == PR_AF_INET6) { size = 16; address = (jbyte *) &addr.ipv6.ip; } else { address = (jbyte *) &addr.inet.ip; } byteArray = JSS_ToByteArray(env, address, size); if (byteArray == NULL) { ASSERT_OUTOFMEM(env); goto finish; } finish: return byteArray; } JNIEXPORT jbyteArray JNICALL Java_org_mozilla_jss_ssl_SocketBase_getLocalAddressByteArrayNative (JNIEnv *env, jobject self) { jbyteArray byteArray=NULL; PRNetAddr addr; jbyte *address=NULL; int size=4; if( JSSL_getSockAddr(env, self, &addr, LOCAL_SOCK) != PR_SUCCESS) { goto finish; } if( PR_NetAddrFamily(&addr) == PR_AF_INET6) { size = 16; address = (jbyte *) &addr.ipv6.ip; } else { address = (jbyte *) &addr.inet.ip; } byteArray = JSS_ToByteArray(env, address, size); if (byteArray == NULL) { ASSERT_OUTOFMEM(env); goto finish; } finish: return byteArray; } /* Leave the original versions of these functions for compatibility */ JNIEXPORT jint JNICALL Java_org_mozilla_jss_ssl_SocketBase_getPeerAddressNative (JNIEnv *env, jobject self) { PRNetAddr addr; if( JSSL_getSockAddr(env, self, &addr, PEER_SOCK) == PR_SUCCESS) { return ntohl(addr.inet.ip); } else { return 0; } } JNIEXPORT jint JNICALL Java_org_mozilla_jss_ssl_SocketBase_getLocalAddressNative(JNIEnv *env, jobject self) { PRNetAddr addr; if( JSSL_getSockAddr(env, self, &addr, LOCAL_SOCK) == PR_SUCCESS ) { return ntohl(addr.inet.ip); } else { return 0; } } JNIEXPORT jint JNICALL Java_org_mozilla_jss_ssl_SocketBase_getLocalPortNative(JNIEnv *env, jobject self) { PRNetAddr addr; if( JSSL_getSockAddr(env, self, &addr, LOCAL_SOCK) == PR_SUCCESS ) { return ntohs(addr.inet.port); } else { return 0; } } /* * This is here for backwards binary compatibility: I didn't want to remove * the symbol from the DLL. This would only get called if someone were using * a pre-3.2 version of the JSS classes with this post-3.2 library. Using * different versions of the classes and the C code is not supported. */ JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SocketBase_setClientCertNicknameNative( JNIEnv *env, jobject self, jstring nick) { PR_ASSERT(0); JSS_throwMsg(env, SOCKET_EXCEPTION, "JSS JAR/DLL mismatch"); } JNIEXPORT void JNICALL Java_org_mozilla_jss_ssl_SocketBase_setClientCert( JNIEnv *env, jobject self, jobject certObj) { JSSL_SocketData *sock = NULL; SECStatus status; CERTCertificate *cert = NULL; PK11SlotInfo *slot = NULL; if( certObj == NULL ) { JSS_throw(env, NULL_POINTER_EXCEPTION); goto finish; } if (JSSL_getSockData(env, self, &sock) != PR_SUCCESS || sock == NULL) goto finish; /* * Store the cert and slot in the SocketData. */ if( JSS_PK11_getCertPtr(env, certObj, &cert) != PR_SUCCESS ) { goto finish; } if( JSS_PK11_getCertSlotPtr(env, certObj, &slot) != PR_SUCCESS ) { goto finish; } if( sock->clientCert != NULL ) { CERT_DestroyCertificate(sock->clientCert); } if( sock->clientCertSlot != NULL ) { PK11_FreeSlot(sock->clientCertSlot); } sock->clientCert = CERT_DupCertificate(cert); sock->clientCertSlot = PK11_ReferenceSlot(slot); /* * Install the callback. */ status = SSL_GetClientAuthDataHook(sock->fd, JSSL_GetClientAuthData, (void*)sock); if(status != SECSuccess) { JSSL_throwSSLSocketException(env, "Unable to set client auth data hook"); goto finish; } finish: EXCEPTION_CHECK(env, sock) } void JSS_SSL_processExceptions(JNIEnv *env, PRFilePrivate *priv) { jthrowable currentExcep; if( priv == NULL ) { return; } currentExcep = (*env)->ExceptionOccurred(env); (*env)->ExceptionClear(env); if( currentExcep != NULL ) { jmethodID processExcepsID; jclass socketBaseClass; jthrowable newException; socketBaseClass = (*env)->FindClass(env, SOCKET_BASE_NAME); if( socketBaseClass == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } processExcepsID = (*env)->GetStaticMethodID(env, socketBaseClass, PROCESS_EXCEPTIONS_NAME, PROCESS_EXCEPTIONS_SIG); if( processExcepsID == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } newException = (*env)->CallStaticObjectMethod(env, socketBaseClass, processExcepsID, currentExcep, JSS_SSL_getException(priv)); if( newException == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } currentExcep = newException; } else { jthrowable excep = JSS_SSL_getException(priv); PR_ASSERT( excep == NULL ); if( excep != NULL ) { (*env)->DeleteGlobalRef(env, excep); } } finish: if( currentExcep != NULL && (*env)->ExceptionOccurred(env) == NULL) { int VARIABLE_MAY_NOT_BE_USED ret = (*env)->Throw(env, currentExcep); PR_ASSERT(ret == 0); } } /* Get the trusted anchor for pkix */ CERTCertificate *getRoot(CERTCertificate *cert, SECCertUsage certUsage) { CERTCertificate *root = NULL; CERTCertListNode *node = NULL; CERTCertList *certList = NULL; if (!cert) { goto finish; } certList = CERT_GetCertChainFromCert(cert, PR_Now(), certUsage); if (certList == NULL) { goto finish; } for (node = CERT_LIST_HEAD(certList); !CERT_LIST_END(node, certList); node = CERT_LIST_NEXT(node)) { /* try to find the root */ if( node->cert && node->cert->isRoot ) { root = CERT_DupCertificate(node->cert) ; } } finish: CERT_DestroyCertList(certList); return root; } /* Internal helper for the below call. */ static SECStatus JSSL_verifyCertPKIXInternal(CERTCertificate *cert, SECCertificateUsage certificateUsage, secuPWData *pwdata, int ocspPolicy, CERTVerifyLog *log, SECCertificateUsage *usage, CERTCertList *trustedCertList) { /* Put the first set of possible flags internally here first. Later * there could be a more complete list to choose from; for now we only * support our hard core fetch AIA OCSP policy. Note that we disable * CRL fetching as Dogtag doesn't support it. Additionally, enable OCSP * checking on the chained CA certificates. Since NSS/PKIX's * CERT_GetClassicOCSPEnabledHardFailurePolicy doesn't do what we want, * we construct the policy ourselves. */ PRUint64 ocsp_Enabled_Hard_Policy_LeafFlags[2] = { /* crl */ CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD, /* ocsp */ CERT_REV_M_TEST_USING_THIS_METHOD | CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO }; PRUint64 ocsp_Enabled_Hard_Policy_ChainFlags[2] = { /* crl */ CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD, /* ocsp */ CERT_REV_M_TEST_USING_THIS_METHOD | CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO }; CERTRevocationMethodIndex ocsp_Enabled_Hard_Policy_Method_Preference[1] = { cert_revocation_method_ocsp }; CERTRevocationFlags ocsp_Enabled_Hard_Policy = { /* CERTRevocationTests - leafTests */ { /* number_of_defined_methods */ 2, /* cert_rev_flags_per_method */ ocsp_Enabled_Hard_Policy_LeafFlags, /* number_of_preferred_methods */ 1, /* preferred_methods */ ocsp_Enabled_Hard_Policy_Method_Preference, /* cert_rev_method_independent_flags */ 0 }, /* CERTRevocationTests - chainTests */ { /* number_of_defined_methods */ 2, /* cert_rev_flags_per_method */ ocsp_Enabled_Hard_Policy_ChainFlags, /* number_of_preferred_methods */ 1, /* preferred_methods */ ocsp_Enabled_Hard_Policy_Method_Preference, /* cert_rev_method_independent_flags */ 0 } }; /* The size of these objects are defined here based upon maximum possible * inputs. A dynamic allocation could reallocate based upon actual usage, * however this would affect the size by at most one or two. Note that, * due to the required usage of cert_pi_end/cert_po_end, these sizes are * inflated by one. */ CERTValOutParam cvout[3] = {{0}}; CERTValInParam cvin[6] = {{0}}; int usageIndex = -1; int inParamIndex = 0; int outParamIndex = 0; SECStatus res = SECFailure; if (cert == NULL) { goto finish; } if (ocspPolicy != OCSP_LEAF_AND_CHAIN_POLICY) { goto finish; } /* Enable live AIA fetching over the network. */ cvin[inParamIndex].type = cert_pi_useAIACertFetch; cvin[inParamIndex].value.scalar.b = PR_TRUE; inParamIndex++; /* By setting the time to zero, we choose the current time when the * check is performed. */ cvin[inParamIndex].type = cert_pi_date; cvin[inParamIndex].value.scalar.time = 0; inParamIndex++; /* Force the strict OCSP check on both the leaf and its chain. */ cvin[inParamIndex].type = cert_pi_revocationFlags; cvin[inParamIndex].value.pointer.revocation = &ocsp_Enabled_Hard_Policy; inParamIndex++; /* Establish a trust anchor if it is passed to us. NOTE: this trust anchor * must previously be validated before it is passed to us here. */ if (trustedCertList != NULL) { cvin[inParamIndex].type = cert_pi_trustAnchors; cvin[inParamIndex].value.pointer.chain = trustedCertList; inParamIndex++; } /* Done establishing input parameters. */ cvin[inParamIndex].type = cert_pi_end; /* When we need to log rationale for failure, pass it as an output * parameter. */ if (log != NULL) { cvout[outParamIndex].type = cert_po_errorLog; cvout[outParamIndex].value.pointer.log = log; outParamIndex ++; } /* When we need to inquire about the resulting certificate usage, pass it * here. */ if (usage != NULL) { usageIndex = outParamIndex; cvout[outParamIndex].type = cert_po_usages; cvout[outParamIndex].value.scalar.usages = 0; outParamIndex ++; } /* Done establishing output parameters. */ cvout[outParamIndex].type = cert_po_end; /* Call into NSS's PKIX library to validate our certificate. */ res = CERT_PKIXVerifyCert(cert, certificateUsage, cvin, cvout, &pwdata); finish: /* Clean up any certificates in the trusted certificate list. This was * a passed input parameter, but by taking ownership of it and clearing it, * we enable tail calls to this function. */ if (trustedCertList) { /* CERT_DestroyCertList destroys interior certs for us. */ CERT_DestroyCertList(trustedCertList); trustedCertList = NULL; } if (res == SECSuccess && usage && usageIndex != -1) { *usage = cvout[usageIndex].value.scalar.usages; } return res; } /* Verify a cert using an explicit PKIX call. For now only perform this call * when the OCSP policy is set to leaf and chain. Performs a blocking, online * OCSP status refresh. The result of this call will be a full-chain OCSP * validation. * * In the future, we'll use ocspPolicy to condition around additional policies * and handle them all with this method (and a call to PKIX). * * Note that this currently requires the certificate to be added directly * to the NSS DB. We can't otherwise validate against root certificates in * the default NSS DB. */ SECStatus JSSL_verifyCertPKIX(CERTCertificate *cert, SECCertificateUsage certificateUsage, secuPWData *pwdata, int ocspPolicy, CERTVerifyLog *log, SECCertificateUsage *usage) { SECCertUsage certUsage = certUsageSSLClient /* 0 */; /* We need to convert the SECCertificateUsage to a SECCertUsage to obtain * the root. */ SECCertificateUsage testUsage = certificateUsage; while (0 != (testUsage = testUsage >> 1)) { certUsage++; } CERTCertificate *root = getRoot(cert, certUsage); // Two cases: either the root is present, or it isn't. if (root == NULL) { /* In this case, we've had a hard time finding the root. In all * likelihood, the following call will fail to validate the end cert * as well and thus fail to validate. I don't believe there's a risk * in trying it however. */ return JSSL_verifyCertPKIXInternal(cert, certificateUsage, pwdata, ocspPolicy, log, usage, NULL); } else { /* In this case, we've found the root certificate. Before passing it * to the leaf, explicitly validate it with strict OCSP checking. Then * validate the leaf certificate with a known and trusted root * certificate. */ SECStatus ret = JSSL_verifyCertPKIXInternal(root, certificateUsageSSLCA, pwdata, ocspPolicy, log, usage, NULL); if (ret != SECSuccess) { return ret; } CERTCertList *rootList = CERT_NewCertList(); CERT_AddCertToListTail(rootList, root); return JSSL_verifyCertPKIXInternal(cert, certificateUsage, pwdata, ocspPolicy, log, usage, rootList); } } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/javasock.c000066400000000000000000000620531412550063600225620ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include #include #include #include "jssutil.h" #include "java_ids.h" #include "jss_exceptions.h" static PRIntn invalidInt() { PR_ASSERT(!"invalidInt called"); return -1; } struct PRFilePrivate { JavaVM *javaVM; jobject sockGlobalRef; jthrowable exception; PRIntervalTime timeout; }; /* * exception should be a global ref */ void setException(JNIEnv *env, PRFilePrivate *priv, jthrowable excep) { PR_ASSERT(priv->exception == NULL); if( priv->exception != NULL) { (*env)->DeleteGlobalRef(env, priv->exception); } priv->exception = excep; } jthrowable JSS_SSL_getException(PRFilePrivate *priv) { jobject retval = priv->exception; priv->exception = NULL; return retval; } #define GET_ENV(vm, env) \ ( ((*(vm))->AttachCurrentThread((vm), (void**)&(env), NULL) == 0) ? 0 : 1 ) static PRInt32 writebuf(JNIEnv *env, PRFileDesc *fd, jobject sockObj, jbyteArray byteArray) { jmethodID getOutputStream, writeMethod; jclass sockClass, osClass; jobject outputStream; jint arrayLen=-1; PRInt32 retval; if( env == NULL ) { goto finish; } /* * get the OutputStream */ sockClass = (*env)->GetObjectClass(env, sockObj); PR_ASSERT(sockClass != NULL); getOutputStream = (*env)->GetMethodID(env, sockClass, SOCKET_GET_OUTPUT_STREAM_NAME, SOCKET_GET_OUTPUT_STREAM_SIG); if(getOutputStream == NULL) { ASSERT_OUTOFMEM(env); goto finish; } outputStream = (*env)->CallObjectMethod(env, sockObj, getOutputStream); if( outputStream == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } /* * get OutputStream.write */ osClass = (*env)->GetObjectClass(env, outputStream); writeMethod = (*env)->GetMethodID(env, osClass, OSTREAM_WRITE_NAME, OSTREAM_WRITE_SIG); if( writeMethod == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } arrayLen = (*env)->GetArrayLength(env, byteArray); /* * Write bytes */ (*env)->CallVoidMethod(env, outputStream, writeMethod, byteArray, 0, arrayLen); /* this may have thrown an IO Exception */ finish: if( env != NULL ) { jthrowable excep = (*env)->ExceptionOccurred(env); if( excep != NULL ) { setException(env, fd->secret, (*env)->NewGlobalRef(env, excep)); (*env)->ExceptionClear(env); retval = -1; PR_SetError(PR_IO_ERROR, 0); } else { retval = arrayLen; } } else { retval = -1; PR_SetError(PR_IO_ERROR, 0); } return retval; } static PRStatus processTimeout(JNIEnv *env, PRFileDesc *fd, jobject sockObj, PRIntervalTime timeout) { jclass socketClass; jmethodID setSoTimeoutMethod; jint javaTimeout; if( timeout == fd->secret->timeout ) { /* no need to change it */ goto finish; } /* * Call setSoTimeout on the Java socket */ socketClass = (*env)->GetObjectClass(env, sockObj); if( socketClass == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } setSoTimeoutMethod = (*env)->GetMethodID(env, socketClass, SET_SO_TIMEOUT_NAME, SET_SO_TIMEOUT_SIG); if( setSoTimeoutMethod == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } if( timeout == PR_INTERVAL_NO_TIMEOUT ) { javaTimeout = 0; /* 0 means no timeout in Java */ } else if( timeout == PR_INTERVAL_NO_WAIT ) { PR_ASSERT(!"PR_INTERVAL_NO_WAIT not supported"); javaTimeout = 1; /* approximate with 1ms wait */ } else { javaTimeout = PR_IntervalToMilliseconds(timeout); } (*env)->CallVoidMethod(env, sockObj, setSoTimeoutMethod, javaTimeout); /* This may have thrown an exception */ fd->secret->timeout = timeout; finish: if( (*env)->ExceptionOccurred(env) ) { return PR_FAILURE; } else { return PR_SUCCESS; } } static PRInt32 jsock_write(PRFileDesc *fd, const PRIOVec *iov, PRInt32 iov_size, PRIntervalTime timeout) { jobject sockObj; JNIEnv *env; jbyteArray outbufArray; PRInt32 retval=-1; if( GET_ENV(fd->secret->javaVM, env) ) goto finish; /* * get the socket */ sockObj = fd->secret->sockGlobalRef; PR_ASSERT(sockObj != NULL); if( processTimeout(env, fd, sockObj, timeout) != PR_SUCCESS ) goto finish; /* * convert iov to java byte array */ { int iovi; jbyte *bytes; int outbufLen; for( iovi = 0, outbufLen = 0; iovi < iov_size; ++iovi) { outbufLen += iov[iovi].iov_len; } PR_ASSERT(outbufLen >= 0); outbufArray = (*env)->NewByteArray(env, outbufLen); if( outbufArray == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } if (!JSS_RefByteArray(env, outbufArray, &bytes, NULL)) { ASSERT_OUTOFMEM(env); goto finish; } for (iovi = 0, outbufLen = 0; iovi < iov_size; ++iovi) { memcpy(bytes+outbufLen,iov[iovi].iov_base, iov[iovi].iov_len); outbufLen += iov[iovi].iov_len; } PR_ASSERT(outbufLen == (*env)->GetArrayLength(env, outbufArray)); JSS_DerefByteArray(env, outbufArray, bytes, 0); } /* * Write bytes */ retval = writebuf(env, fd, sockObj, outbufArray); finish: /* nothing to free, nothing to return */ if( env != NULL ) { jthrowable excep = (*env)->ExceptionOccurred(env); if( excep != NULL ) { setException(env, fd->secret, (*env)->NewGlobalRef(env, excep)); (*env)->ExceptionClear(env); retval = -1; PR_SetError(PR_IO_ERROR, 0); } } else { retval = -1; PR_SetError(PR_IO_ERROR, 0); } return retval; } typedef enum { LOCAL_NAME, PEER_NAME } LocalOrPeer; static PRStatus getInetAddress(PRFileDesc *fd, PRNetAddr *addr, LocalOrPeer localOrPeer) { PRStatus status = PR_FAILURE; jobject sockObj; JNIEnv *env; jobject inetAddress; jbyteArray addrByteArray; jint port; int addrBALen = 0; if( GET_ENV(fd->secret->javaVM, env) ) goto finish; /* * get the socket */ sockObj = fd->secret->sockGlobalRef; PR_ASSERT(sockObj != NULL); /* * get the InetAddress and port */ { jclass sockClass = (*env)->GetObjectClass(env, sockObj); jmethodID getInetAddrMethod; jmethodID getPortMethod; const char *getAddrMethodName; const char *getPortMethodName; if( localOrPeer == LOCAL_NAME ) { getAddrMethodName = GET_LOCAL_ADDR_NAME; getPortMethodName = GET_LOCAL_PORT_NAME; } else { PR_ASSERT(localOrPeer == PEER_NAME); getAddrMethodName = GET_INET_ADDR_NAME; getPortMethodName = GET_PORT_NAME; } PR_ASSERT( sockClass != NULL ); getInetAddrMethod = (*env)->GetMethodID(env, sockClass, getAddrMethodName, GET_INET_ADDR_SIG); if( getInetAddrMethod == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } inetAddress = (*env)->CallObjectMethod(env, sockObj, getInetAddrMethod); if( inetAddress == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } if( (*env)->ExceptionOccurred(env) ) goto finish; getPortMethod = (*env)->GetMethodID(env, sockClass, getPortMethodName, GET_PORT_SIG); if( getPortMethod == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } port = (*env)->CallIntMethod(env, sockObj, getPortMethod); if( (*env)->ExceptionOccurred(env) ) goto finish; } /* * get the address as a byte array */ { jclass inetAddrClass = (*env)->GetObjectClass(env, inetAddress); jmethodID getAddressMethod; PR_ASSERT(inetAddrClass != NULL); getAddressMethod = (*env)->GetMethodID(env, inetAddrClass, GET_ADDR_NAME, GET_ADDR_SIG); if( getAddressMethod == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } addrByteArray = (*env)->CallObjectMethod(env, inetAddress, getAddressMethod); if( addrByteArray == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } } /* * convert to a PRNetAddr */ { jbyte *addrBytes; memset(addr, 0, sizeof(PRNetAddr)); addrBALen = (*env)->GetArrayLength(env, addrByteArray); PR_ASSERT( (addrBALen == 4) || (addrBALen == 16 ) ); /* make sure you release them later */ if (!JSS_RefByteArray(env, addrByteArray, &addrBytes, NULL)) { ASSERT_OUTOFMEM(env); goto finish; } /* ip field is in network byte order */ if (addrBALen == 4) { memcpy( (void*) &addr->inet.ip, addrBytes, 4); addr->inet.family = PR_AF_INET; addr->inet.port = port; } else { memcpy( (void*) &addr->ipv6.ip,addrBytes, 16); addr->inet.family = PR_AF_INET6; addr->inet.port = port; } JSS_DerefByteArray(env, addrByteArray, addrBytes, JNI_ABORT); } status = PR_SUCCESS; finish: if( env != NULL ) { jthrowable excep = (*env)->ExceptionOccurred(env); if( excep != NULL ) { setException(env, fd->secret, (*env)->NewGlobalRef(env, excep)); (*env)->ExceptionClear(env); status = PR_FAILURE; PR_SetError(PR_IO_ERROR, 0); } } else { status = PR_FAILURE; PR_SetError(PR_IO_ERROR, 0); } return status; } static PRStatus jsock_getPeerName(PRFileDesc *fd, PRNetAddr *addr) { return getInetAddress(fd, addr, PEER_NAME); } static PRStatus jsock_getSockName(PRFileDesc *fd, PRNetAddr *addr) { return getInetAddress(fd, addr, LOCAL_NAME); } static PRInt32 jsock_send(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { JNIEnv *env; jobject sockObj; jbyteArray byteArray; PRInt32 retval = -1;; if( GET_ENV(fd->secret->javaVM, env) ) goto finish; /* * get the socket */ sockObj = fd->secret->sockGlobalRef; PR_ASSERT(sockObj != NULL); if( processTimeout(env, fd, sockObj, timeout) != PR_SUCCESS ) goto finish; /* * Turn buf into byte array */ byteArray = JSS_ToByteArray(env, buf, amount); if (byteArray == NULL) { ASSERT_OUTOFMEM(env); goto finish; } retval = writebuf(env, fd, sockObj, byteArray); finish: if( env != NULL ) { jthrowable excep = (*env)->ExceptionOccurred(env); if( excep != NULL ) { setException(env, fd->secret, (*env)->NewGlobalRef(env, excep)); (*env)->ExceptionClear(env); retval = -1; PR_SetError(PR_IO_ERROR, 0); } } else { retval = -1; PR_SetError(PR_IO_ERROR, 0); } return retval; } static PRInt32 jsock_recv(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { PRInt32 retval=-1; JNIEnv *env; jobject sockObj; jbyteArray byteArray; jobject inputStream; if( GET_ENV(fd->secret->javaVM, env) ) goto finish; /* * get the socket */ sockObj = fd->secret->sockGlobalRef; PR_ASSERT(sockObj != NULL); if( processTimeout(env, fd, sockObj, timeout) != PR_SUCCESS ) goto finish; /* * get InputStream */ { jclass sockClass = (*env)->GetObjectClass(env, sockObj); jmethodID getInputStreamMethod; if( sockClass == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } getInputStreamMethod = (*env)->GetMethodID(env, sockClass, SOCKET_GET_INPUT_STREAM_NAME, SOCKET_GET_INPUT_STREAM_SIG); if( getInputStreamMethod == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } inputStream = (*env)->CallObjectMethod(env, sockObj, getInputStreamMethod); if( inputStream == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } } /* create new, empty byte array */ byteArray = (*env)->NewByteArray(env, amount); if( byteArray == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } /* * call read() */ { jclass isClass = (*env)->GetObjectClass(env, inputStream); jmethodID readMethod; if( isClass == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } readMethod = (*env)->GetMethodID(env, isClass, ISTREAM_READ_NAME, ISTREAM_READ_SIG); if( readMethod == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } retval = (*env)->CallIntMethod(env, inputStream, readMethod, byteArray); if( (*env)->ExceptionOccurred(env) ) { goto finish; } else if( retval == -1 ) { /* Java EOF == -1, NSPR EOF == 0 */ retval = 0; } else if( retval == 0 ) { /* timeout */ PR_ASSERT( fd->secret->timeout != PR_INTERVAL_NO_TIMEOUT ); PR_SetError(PR_IO_TIMEOUT_ERROR, 0); retval = -1; } PR_ASSERT(retval <= amount); } /* * copy byte array to buf */ if( retval > 0 ) { jbyte *bytes; bytes = (*env)->GetByteArrayElements(env, byteArray, NULL); if (bytes != NULL) { memcpy(buf, bytes, retval); JSS_DerefByteArray(env, byteArray, bytes, JNI_ABORT); } else { JSS_throwMsg(env, OUT_OF_MEMORY_ERROR, "Unable to get byte array elements."); } } finish: if( env ) { jthrowable excep = (*env)->ExceptionOccurred(env); if( excep != NULL ) { setException(env, fd->secret, excep); (*env)->ExceptionClear(env); retval = -1; PR_SetError(PR_IO_ERROR, 0); } } else { retval = -1; PR_SetError(PR_IO_ERROR, 0); } return retval; } static jboolean getBooleanProperty(JNIEnv *env, jobject sock, const char* methodName) { jclass sockClass; jmethodID method; jboolean retval = JNI_FALSE; sockClass = (*env)->GetObjectClass(env, sock); if( sockClass == NULL ) goto finish; method = (*env)->GetMethodID(env, sockClass, methodName, "()Z"); if( method == NULL ) goto finish; retval = (*env)->CallBooleanMethod(env, sock, method); finish: return retval; } static jint getIntProperty(JNIEnv *env, jobject sock, const char* methodName) { jclass sockClass; jmethodID method; jint retval=0; sockClass = (*env)->GetObjectClass(env, sock); if( sockClass == NULL ) goto finish; method = (*env)->GetMethodID(env, sockClass, methodName, "()I"); if( method == NULL ) goto finish; retval = (*env)->CallIntMethod(env, sock, method); finish: return retval; } static void setBooleanProperty(JNIEnv *env, jobject sock, const char* methodName, jboolean value) { jclass sockClass; jmethodID method; sockClass = (*env)->GetObjectClass(env, sock); if( sockClass == NULL ) goto finish; method = (*env)->GetMethodID(env, sockClass, methodName, "(Z)V"); if( method == NULL ) goto finish; (*env)->CallVoidMethod(env, sock, method, value); finish: return; } static void setIntProperty(JNIEnv *env, jobject sock, const char* methodName, jint value) { jclass sockClass; jmethodID method; sockClass = (*env)->GetObjectClass(env, sock); if( sockClass == NULL ) goto finish; method = (*env)->GetMethodID(env, sockClass, methodName, "(I)V"); if( method == NULL ) goto finish; (*env)->CallVoidMethod(env, sock, method, value); finish: return; } static void getSoLinger(JNIEnv *env, jobject sock, PRLinger *linger) { jint lingSecs; lingSecs = getIntProperty(env, sock, "getSoLinger"); if( (*env)->ExceptionOccurred(env) ) goto finish; if( lingSecs == -1 ) { linger->polarity = PR_FALSE; } else { linger->polarity = PR_TRUE; linger->linger = PR_SecondsToInterval(lingSecs); } finish: return; } static void setSoLinger(JNIEnv *env, jobject sock, PRLinger *linger) { jint lingSecs; jclass clazz; jmethodID methodID; jboolean onoff; if( linger->polarity == PR_FALSE ) { onoff = JNI_FALSE; lingSecs = 0; /* this should be ignored */ } else { onoff = JNI_TRUE; lingSecs = PR_IntervalToSeconds(linger->linger); } clazz = (*env)->GetObjectClass(env, sock); if( clazz == NULL ) goto finish; methodID = (*env)->GetMethodID(env, clazz, "setSoLinger", "(ZI)V"); if( methodID == NULL) goto finish; (*env)->CallVoidMethod(env, sock, methodID, onoff, lingSecs); finish: return; } static PRStatus jsock_getSockOpt(PRFileDesc *fd, PRSocketOptionData *data) { PRStatus retval = PR_SUCCESS; JNIEnv *env; jobject sockObj; if( GET_ENV(fd->secret->javaVM, env) ) goto finish; /* * get the socket */ sockObj = fd->secret->sockGlobalRef; PR_ASSERT(sockObj != NULL); switch(data->option) { case PR_SockOpt_Nonblocking: data->value.non_blocking = PR_FALSE; break; case PR_SockOpt_Keepalive: data->value.keep_alive = getBooleanProperty(env, sockObj, "getKeepAlive") == JNI_TRUE ? PR_TRUE : PR_FALSE; break; case PR_SockOpt_RecvBufferSize: data->value.send_buffer_size = getIntProperty(env, sockObj, "getReceiveBufferSize"); break; case PR_SockOpt_SendBufferSize: data->value.recv_buffer_size = getIntProperty(env, sockObj, "getSendBufferSize"); break; case PR_SockOpt_Linger: getSoLinger( env, sockObj, & data->value.linger ); break; case PR_SockOpt_NoDelay: data->value.no_delay = getBooleanProperty(env, sockObj,"getTcpNoDelay"); break; default: retval = PR_FAILURE; break; } finish: if( env != NULL ) { jthrowable excep = (*env)->ExceptionOccurred(env); if( excep != NULL ) { setException(env, fd->secret, (*env)->NewGlobalRef(env, excep)); (*env)->ExceptionClear(env); retval = PR_FAILURE; PR_SetError(PR_IO_ERROR, 0); } } else { retval = PR_FAILURE; PR_SetError(PR_IO_ERROR, 0); } return retval; } static PRStatus jsock_setSockOpt(PRFileDesc *fd, PRSocketOptionData *data) { PRStatus retval = PR_SUCCESS; JNIEnv *env; jobject sockObj; if( GET_ENV(fd->secret->javaVM, env) ) goto finish; /* * get the socket */ sockObj = fd->secret->sockGlobalRef; PR_ASSERT(sockObj != NULL); switch(data->option) { case PR_SockOpt_Keepalive: setBooleanProperty(env, sockObj, "setKeepAlive",data->value.keep_alive); break; case PR_SockOpt_Linger: setSoLinger(env, sockObj, &data->value.linger); break; case PR_SockOpt_RecvBufferSize: setIntProperty(env, sockObj, "setReceiveBufferSize", data->value.recv_buffer_size); break; case PR_SockOpt_SendBufferSize: setIntProperty(env, sockObj, "setSendBufferSize", data->value.send_buffer_size); break; case PR_SockOpt_NoDelay: setBooleanProperty(env, sockObj, "setTcpNoDelay", data->value.no_delay); break; default: retval = PR_FAILURE; break; } finish: if( env != NULL ) { jthrowable excep = (*env)->ExceptionOccurred(env); if( excep != NULL ) { setException(env, fd->secret, (*env)->NewGlobalRef(env, excep)); (*env)->ExceptionClear(env); retval = PR_FAILURE; PR_SetError(PR_IO_ERROR, 0); } } else { retval = PR_FAILURE; PR_SetError(PR_IO_ERROR, 0); } return retval; } static PRStatus jsock_close(PRFileDesc *fd) { PRStatus retval = PR_FAILURE; JNIEnv *env; jobject sockObj; jclass sockClass; jmethodID closeMethod; jthrowable excep; if( GET_ENV(fd->secret->javaVM, env) ) goto finish; /* * get the socket */ sockObj = fd->secret->sockGlobalRef; PR_ASSERT(sockObj != NULL); /* * Get the close method */ sockClass = (*env)->GetObjectClass(env, sockObj); if( sockClass == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } closeMethod = (*env)->GetMethodID(env, sockClass, SOCKET_CLOSE_NAME, SOCKET_CLOSE_SIG); if( closeMethod == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } /* * call the close method */ (*env)->CallVoidMethod(env, sockObj, closeMethod); /* * Free the PRFilePrivate */ (*env)->DeleteGlobalRef(env, fd->secret->sockGlobalRef); if( (excep = JSS_SSL_getException(fd->secret)) != NULL ) { (*env)->DeleteGlobalRef(env, excep); } PR_Free(fd->secret); fd->secret = NULL; retval = PR_SUCCESS; finish: /* * If an exception was thrown, we can't put it in the fd because we * just deleted it. So instead, we're going to let it ride and check for * it up in socketClose(). */ if( env ) { if( (*env)->ExceptionOccurred(env) != NULL ) { retval = PR_FAILURE; PR_SetError(PR_IO_ERROR, 0); } } else { retval = PR_FAILURE; PR_SetError(PR_IO_ERROR, 0); } return retval; } static PRStatus jsock_shutdown(PRFileDesc *fd, PRShutdownHow how) { PRStatus retval = PR_FAILURE; JNIEnv *env; jobject sockObj; jmethodID methodID; jclass clazz; if( GET_ENV(fd->secret->javaVM, env) ) goto finish; /* * get the socket */ sockObj = fd->secret->sockGlobalRef; PR_ASSERT(sockObj != NULL); clazz = (*env)->GetObjectClass(env, sockObj); if( clazz == NULL ) goto finish; if( how == PR_SHUTDOWN_SEND || how == PR_SHUTDOWN_BOTH ) { methodID = (*env)->GetMethodID(env, clazz, "shutdownOutput", "()V"); if( methodID == NULL ) goto finish; (*env)->CallVoidMethod(env, sockObj, methodID); } if( (*env)->ExceptionOccurred(env) ) goto finish; if( how == PR_SHUTDOWN_RCV || how == PR_SHUTDOWN_BOTH ) { methodID = (*env)->GetMethodID(env, clazz, "shutdownInput", "()V"); if( methodID == NULL ) goto finish; (*env)->CallVoidMethod(env, sockObj, methodID); } retval = PR_SUCCESS; finish: if( env != NULL ) { jthrowable excep = (*env)->ExceptionOccurred(env); if( excep != NULL ) { setException(env, fd->secret, (*env)->NewGlobalRef(env, excep)); (*env)->ExceptionClear(env); retval = PR_FAILURE; PR_SetError(PR_IO_ERROR, 0); } } else { retval = PR_FAILURE; PR_SetError(PR_IO_ERROR, 0); } return retval; } static const PRIOMethods jsockMethods = { PR_DESC_SOCKET_TCP, (PRCloseFN) jsock_close, (PRReadFN) invalidInt, (PRWriteFN) invalidInt, (PRAvailableFN) invalidInt, (PRAvailable64FN) invalidInt, (PRFsyncFN) invalidInt, (PRSeekFN) invalidInt, (PRSeek64FN) invalidInt, (PRFileInfoFN) invalidInt, (PRFileInfo64FN) invalidInt, (PRWritevFN) jsock_write, (PRConnectFN) invalidInt, (PRAcceptFN) invalidInt, (PRBindFN) invalidInt, (PRListenFN) invalidInt, (PRShutdownFN) jsock_shutdown, (PRRecvFN) jsock_recv, (PRSendFN) jsock_send, (PRRecvfromFN) invalidInt, (PRSendtoFN) invalidInt, (PRPollFN) invalidInt, (PRAcceptreadFN) invalidInt, (PRTransmitfileFN) invalidInt, (PRGetsocknameFN) jsock_getSockName, (PRGetpeernameFN) jsock_getPeerName, (PRReservedFN) invalidInt, (PRReservedFN) invalidInt, (PRGetsocketoptionFN) jsock_getSockOpt, (PRSetsocketoptionFN) jsock_setSockOpt, (PRSendfileFN) invalidInt, (PRConnectcontinueFN) invalidInt, (PRReservedFN) invalidInt, (PRReservedFN) invalidInt, (PRReservedFN) invalidInt, (PRReservedFN) invalidInt }; static void jsockDestructor(PRFileDesc *fd) { PR_ASSERT(!"This destructor shouldn't be called. close() does the work"); } PRFileDesc* JSS_SSL_javasockToPRFD(JNIEnv *env, jobject sockObj) { PRFileDesc *fd; JavaVM *vm; if( (*env)->GetJavaVM(env, &vm) != 0 ) { return NULL; } fd = PR_NEW(PRFileDesc); if( fd ) { fd->methods = &jsockMethods; fd->secret = PR_NEW(PRFilePrivate); fd->secret->sockGlobalRef = (*env)->NewGlobalRef(env, sockObj); fd->secret->javaVM = vm; fd->secret->exception = NULL; fd->secret->timeout = PR_INTERVAL_NO_TIMEOUT; fd->lower = fd->higher = NULL; fd->dtor = jsockDestructor; } else { /* OUT OF MEM */ } return fd; } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/javax/000077500000000000000000000000001412550063600217205ustar00rootroot00000000000000jss-5.0.0/src/main/java/org/mozilla/jss/ssl/javax/BufferPRFD.c000066400000000000000000000321321412550063600237520ustar00rootroot00000000000000#include /* Necessary for correctly propagating E_WOULDBLOCK. */ #include #include #include /* Ring buffer implementation to handle read/write calls. */ #include "j_buffer.h" #include "BufferPRFD.h" /* This struct stores all the private data we need access to from inside our * PRFileDesc calls. We store the following information: * * read_bytes -- raw buffer to read from for recv(...) calls * read_capacity -- size of read_bytes buffer * read_ptr -- location after the last character in the buffer; * i.e., location to place the next character if writing. * * write_bytes -- raw buffer to write to for send(...) calls * write_capacity -- size of write_bytes buffer * write_ptr -- location after the last character in the buffer; * i.e., location to place the next character if writing. * * peer_addr -- peer address info, truncated to 16 bytes * * As the read_* and write_* members should be provided by the creator, and * actors outside our PRFileDesc need access to this information (to add more * bytes to the read buffer when more data arrives for instance), we store * pointers and not the values themselves. * * The creator is responsible for ensuring that all data gets correctly freed * when the program exits; we will not free any of our pointers that were not * created by us. */ struct PRFilePrivate { j_buffer *read_buffer; j_buffer *write_buffer; uint8_t *peer_addr; }; static PRDescIdentity buffer_layer_id = 0; // This function is provided as a stub for all unimplemented calls. static PRIntn invalidInternalCall(/* anything */) { // For debugging; any invalid calls are asserted, so we can get a full // backtrace from the debugger and _hopefully_ we can find out which call // was attempted. To enable asserts, define DEBUG or FORCE_PR_ASSERT // before loading the NSPR headers, e.g., by using the DEBUG release type // during CMake configuration time. PR_ASSERT(!"invalidInternalCall performed!"); return 0; } // This function mimics shutting down a buffer. static PRStatus PRBufferShutdown(PRFileDesc *fd, PRIntn how) { // This method has no functionality; we're a lower level under both // the SSLEngine and NSS's SSL context. When the application issues // a shutdown request, SSLEngine refuses to allow new writes (and only // reads until the remote party acknowledges the shutdown). All data // should be written into the NSS connection buffer and NSS's shutdown // should be called. At this point, there's nothing left for us to do: // there's no TCP socket we need to terminate, and we need to allow // any remaining buffered bytes to be written. So, the only thing we // can do is return success here. return PR_SUCCESS; } // This function mimics closing a buffer and frees our associated data. static PRStatus PRBufferClose(PRFileDesc *fd) { PRStatus rv = PR_SUCCESS; if (fd->secret != NULL) { // We intentionally don't free read_buffer or write_buffer; we assume // the caller has a copy of these data structures as well, and could // still be reading after the PRFileDesc is closed. fd->secret->read_buffer = NULL; fd->secret->write_buffer = NULL; // Free the peer address we allocated during initialiation. free(fd->secret->peer_addr); fd->secret->peer_addr = NULL; // Free our internal data structure. free(fd->secret); fd->secret = NULL; } PR_ASSERT(fd->identity == buffer_layer_id); PR_ASSERT(fd->higher == NULL); PR_ASSERT(fd->lower == NULL); fd->dtor(fd); return rv; } // Fake getting the name of the remote peer static PRStatus PRBufferGetPeerName(PRFileDesc *fd, PRNetAddr *addr) { /* getPeerName takes a PRFileDesc and modifies the PRNetAddr with the * name of the peer. Because of the specifics of the NSS Implementation, * we return whatever name was passed to us on creation; we lack a real * TCP socket and thus a real TCP name. * * However, we have to provide the peer name as type IPv6, else it either * gets mangled by the IPv4 -> IPv6 translation or a * PR_ADDRESS_NOT_SUPPORTED_ERROR is thrown by ssl_GetPeerInfo(...). */ /* There are three main places this is called in a normal TLS connection: * * ssl_ImportFD(...) -- where the result of this function is compared * to PR_SUCCESS to see if it is connected * ssl_BeginClientHandshake(...) -- where this function sets local * values for session resumption on * the client * ssl3_HandleClientHello(...) -- where this function sets local * values for evaluating session * resumption from the client. * * Because these results have to be consistent for session resumption to * work, we must query the internal structure and return that value. * Note that it isn't a security risk if an incorrect peer_addr is * provided to us: the other party must _also_ know the session keys for * this to matter. */ // https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSPR/Reference/PRNetAddr if (fd->secret == NULL || addr == NULL) { return PR_FAILURE; } PRFilePrivate *internal = fd->secret; addr->ipv6.family = PR_AF_INET6; addr->ipv6.port = 0xFFFF; addr->ipv6.flowinfo = 0x00000000; // We validate that strlen(peer_addr) <= 16 on creation by truncating // it to 16 bytes. Thus the memcpy with strlen(...) won't overflow the // size of ipv6.ip. memset(&addr->ipv6.ip, 0, 16); memcpy(&addr->ipv6.ip, internal->peer_addr, 16); return PR_SUCCESS; } // Respond to send requests static PRInt32 PRBufferSend(PRFileDesc *fd, const void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { /* Send takes a PRFileDesc and attempts to send some amount of bytes from * the start of buf to the other party before timeout is reached. Because * we're implementing this as a buffer, copy into the buffer if there is * free space, else return EWOULDBLOCK. */ PRFilePrivate *internal = fd->secret; if (!jb_can_write(internal->write_buffer)) { /* Under correct Unix non-blocking socket semantics, if we lack data * to write, return a negative length and set EWOULDBLOCK. This is * documented in `man 2 recv`. */ PR_SetError(PR_WOULD_BLOCK_ERROR, EWOULDBLOCK); return -1; } /* By checking if we can write, we ensure we don't return 0 from * jb_write(...); otherwise, we'd violate non-blocking socket * semantics. */ return jb_write(internal->write_buffer, (const uint8_t *) buf, amount); } // Respond to write requests static PRInt32 PRBufferWrite(PRFileDesc *fd, const void *buf, PRInt32 amount) { /* Write is the same as Send except that it doesn't have a timeout or * understand flags. Since our implementation of Send is fake, pass * arbitrary data and use it to implement Write as well. */ return PRBufferSend(fd, buf, amount, 0, -1); } // Respond to recv requests static PRInt32 PRBufferRecv(PRFileDesc *fd, void *buf, PRInt32 amount, PRIntn flags, PRIntervalTime timeout) { /* Recv takes a PRFileDesc and attempts to read some amount of bytes from * the start of buf to return to the caller before timeout is reached. * Because we're implementing this as a buffer, copy from the buffer when * there is something in it, else return EWOULDBLOCK. */ PRFilePrivate *internal = fd->secret; if (!jb_can_read(internal->read_buffer)) { /* See comment in PRBufferSend about EWOULDBLOCK. */ PR_SetError(PR_WOULD_BLOCK_ERROR, EWOULDBLOCK); return -1; } /* By checking if we can read, we ensure we don't return 0 from * jb_read(...); otherwise, we'd violate non-blocking socket * semantics. */ return jb_read(internal->read_buffer, (uint8_t *) buf, amount); } // Respond to read requests static PRInt32 PRBufferRead(PRFileDesc *fd, void *buf, PRInt32 amount) { /* Read is the same as Recv except that it doesn't have a timeout or * understand flags. Since our implementation of Recv is fake, pass * arbitrary data and use it to implement Read as well. */ return PRBufferRecv(fd, buf, amount, 0, -1); } // Fake responses to getSocketOption requests static PRStatus PRBufferGetSocketOption(PRFileDesc *fd, PRSocketOptionData *data) { /* getSocketOption takes a PRFileDesc and modifies the value field of data * with socket option specified in the option field. We fake responses with * a couple of sane defaults here: * * non_blocking = true * reuse_addr = true * keep_alive = false * no_delay = true * * We return valid responses to three other options: * * max_segment = capacity of read_buffer * recv_buffer_size = capacity of read buffer * send_buffer_size = capacity of write buffer * * Note that all responses are "fake" in that calls to SetSocketOption will * not be reflected here. */ if (!data || !fd) { return PR_FAILURE; } PRFilePrivate *internal = fd->secret; switch (data->option) { case PR_SockOpt_Nonblocking: data->value.non_blocking = PR_TRUE; return PR_SUCCESS; case PR_SockOpt_Reuseaddr: data->value.reuse_addr = PR_TRUE; return PR_SUCCESS; case PR_SockOpt_Keepalive: data->value.keep_alive = PR_FALSE; return PR_SUCCESS; case PR_SockOpt_NoDelay: data->value.no_delay = PR_TRUE; return PR_SUCCESS; case PR_SockOpt_MaxSegment: data->value.max_segment = jb_capacity(internal->read_buffer); return PR_SUCCESS; case PR_SockOpt_RecvBufferSize: data->value.recv_buffer_size = jb_capacity(internal->read_buffer); return PR_SUCCESS; case PR_SockOpt_SendBufferSize: data->value.send_buffer_size = jb_capacity(internal->write_buffer); return PR_SUCCESS; default: return PR_FAILURE; } } // Fake responses to setSocketOption static PRStatus PRBufferSetSocketOption(PRFileDesc *fd, const PRSocketOptionData *data) { /* This gives the caller control over setting socket options. It is the * equivalent of fcntl() with F_SETFL. In our case, O_NONBLOCK is the * only thing passed in, which we always return as true anyways, so * ignore the result. */ return PR_SUCCESS; } // Create a method table with all our implemented functions static const PRIOMethods PRIOBufferMethods = { PR_DESC_SOCKET_TCP, PRBufferClose, PRBufferRead, PRBufferWrite, (PRAvailableFN)invalidInternalCall, (PRAvailable64FN)invalidInternalCall, (PRFsyncFN)invalidInternalCall, (PRSeekFN)invalidInternalCall, (PRSeek64FN)invalidInternalCall, (PRFileInfoFN)invalidInternalCall, (PRFileInfo64FN)invalidInternalCall, (PRWritevFN)invalidInternalCall, (PRConnectFN)invalidInternalCall, (PRAcceptFN)invalidInternalCall, (PRBindFN)invalidInternalCall, (PRListenFN)invalidInternalCall, PRBufferShutdown, PRBufferRecv, PRBufferSend, (PRRecvfromFN)invalidInternalCall, (PRSendtoFN)invalidInternalCall, (PRPollFN)invalidInternalCall, (PRAcceptreadFN)invalidInternalCall, (PRTransmitfileFN)invalidInternalCall, (PRGetsocknameFN)invalidInternalCall, PRBufferGetPeerName, (PRReservedFN)invalidInternalCall, (PRReservedFN)invalidInternalCall, PRBufferGetSocketOption, PRBufferSetSocketOption, (PRSendfileFN)invalidInternalCall, (PRConnectcontinueFN)invalidInternalCall, (PRReservedFN)invalidInternalCall, (PRReservedFN)invalidInternalCall, (PRReservedFN)invalidInternalCall, (PRReservedFN)invalidInternalCall }; /* Construct a new PRFileDesc backed by a pair of buffers. Note that these * should be separate buffers, but need not be unique to this PRFileDesc; * that is, a client and server could share (but be swapped) j_buffers. * The caller is expected to provide a peer_info to be used for optional * session resumption; this will be truncated at 16 bytes of data, and * extended with nulls if it is shorter. It is suggested that this be an IPv4 * or IPv6 address. Note that this value is not used to validate the hostname * in any way (see SSL_SetURL to validate the peer). */ PRFileDesc *newBufferPRFileDesc(j_buffer *read_buf, j_buffer *write_buf, uint8_t *peer_info, size_t peer_info_len) { PRFileDesc *fd; if (buffer_layer_id == 0) { buffer_layer_id = PR_GetUniqueIdentity("Buffer"); } fd = PR_CreateIOLayerStub(buffer_layer_id, &PRIOBufferMethods); if (fd) { fd->secret = PR_NEW(PRFilePrivate); fd->secret->read_buffer = read_buf; fd->secret->write_buffer = write_buf; size_t len = peer_info_len; if (len > 16) { len = 16; } fd->secret->peer_addr = calloc(16, sizeof(uint8_t)); memcpy(fd->secret->peer_addr, peer_info, len); } return fd; } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/javax/BufferPRFD.h000066400000000000000000000025731412550063600237650ustar00rootroot00000000000000#include /* Necessary for correctly propagating E_WOULDBLOCK. */ #include #include #include /* Ring buffer implementation to handle read/write calls. */ #include "j_buffer.h" /* Use a modern pragma guard... */ #pragma once /* Free a Buffer-backed PRFileDesc. Note that it is usually sufficient to call * PR_Close(...) on the buffer instead. This is provided for completeness and * should not be called in a SSL context as the buffer PRFileDesc is wrapped * by the SSL PRFileDesc. Note that this only removes references to the * underlying j_buffers and does not free them; it is up to the caller to * do so. */ void freeBufferPRFileDesc(PRFileDesc *fd); /* Construct a new PRFileDesc backed by a pair of buffers. Note that these * should be separate buffers, but need not be unique to this PRFileDesc; * that is, a client and server could share (but be swapped) j_buffers. * The caller is expected to provide a peer_info to be used for optional * session resumption; this will be truncated at 16 bytes of data, and * extended with nulls if it is shorter. It is suggested that this be an IPv4 * or IPv6 address. Note that this value is not used to validate the hostname * in any way (see SSL_SetURL to validate the peer). */ PRFileDesc *newBufferPRFileDesc(j_buffer *read_buf, j_buffer *write_buf, uint8_t *peer_info, size_t peer_info_len); jss-5.0.0/src/main/java/org/mozilla/jss/ssl/javax/JSSEngine.java000066400000000000000000001065541412550063600243630ustar00rootroot00000000000000package org.mozilla.jss.ssl.javax; import java.util.ArrayList; import java.util.HashMap; import java.util.concurrent.atomic.AtomicBoolean; import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLException; import javax.net.ssl.SSLParameters; import javax.net.ssl.X509KeyManager; import javax.net.ssl.X509TrustManager; import org.mozilla.jss.crypto.Policy; import org.mozilla.jss.nss.PR; import org.mozilla.jss.nss.PRFDProxy; import org.mozilla.jss.nss.SSL; import org.mozilla.jss.nss.SSLFDProxy; import org.mozilla.jss.nss.SecurityStatusResult; import org.mozilla.jss.pkcs11.PK11Cert; import org.mozilla.jss.pkcs11.PK11PrivKey; import org.mozilla.jss.provider.javax.crypto.JSSKeyManager; import org.mozilla.jss.provider.javax.crypto.JSSTrustManager; import org.mozilla.jss.ssl.SSLCipher; import org.mozilla.jss.ssl.SSLVersion; import org.mozilla.jss.ssl.SSLVersionRange; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * JSS's SSLEngine base class for alternative implementations. * * This abstracts out many components for all JSS SSLEngine implementations, * such as cipher suite support, SSLSession creation, and various other * common functions. This allows alternative SSLEngine implementations to * focus on two main things: wrap/unwrap and init. * * There are the following implementations: * - JSSEngineReferenceImpl - A reference implementation with extensive * logging and debugging. * * Usually a JSSEngine isn't constructed directly, but instead accessed via * the Provider mechanism, SSLContext. See JSSContextSpi for more information. */ public abstract class JSSEngine extends javax.net.ssl.SSLEngine { public static Logger logger = LoggerFactory.getLogger(JSSEngine.class); /** * Size of the underlying BUFFERs. * * Helps to be large enough to fit most common SSL packets during the * initial handshake. */ protected static int BUFFER_SIZE = 1 << 12; /** * Whether or not this SSLEngine is acting as the client end of the * handshake. */ protected boolean as_server; /** * Peer's hostname, used for certificate validation. * */ protected String hostname; /** * Certificate alias used by the JSSEngine instance. */ protected String certAlias; /** * Certificate used by this JSSEngine instance. * * Selected and inferred from the KeyManagers passed, when not passed * explicitly (either during construction or with a call to * setKeyMaterials(...)). */ protected PK11Cert cert; /** * Key corresponding to the local certificate. */ protected PK11PrivKey key; /** * A list of all KeyManagers available to this JSSEngine instance. * * Note: currently only a single JSSKeyManager instance is exposed, * and it can only handle finding a single certificate by nickname. * In the future, more KeyManagers should be supported. */ protected X509KeyManager[] key_managers; /** * A list of all TrustManagers available to this JSSEngine instance. * * The behavior of this list depends on how which TrustManagers are * passed. */ protected X509TrustManager[] trust_managers; /** * Whether or not we should fail to handshake if client authentication * is not passed by the peer and we are a server; if we are a client, * whether or not we offer our certificate to the server. * * See also the note for want_client_auth. */ protected boolean need_client_auth; /** * Whether or not we should attempt to handshake with client * authentication. * * Note that under a strict reading of the SSLEngine spec, this is * mutually exclusive with need_client_auth: either want_client_auth * or need_client_auth can be true, but not both. However, both can * be false. * * Under NSS semantics however, we have control over two values: whether * we offer/request client auth, and whether we should fail to handshake * if we don't get client auth. This doesn't quite map onto the want/need * semantics, but it is what we have available. */ protected boolean want_client_auth; /** * What the official SSLEngineResult handshake status is, at the present * time. * * Note that while we store the current handshake state in JSSEngine, we * don't implement getHandshakeStatus(...), as different JSSEngine * implementations could have different implementations for that method. */ protected SSLEngineResult.HandshakeStatus handshake_state = SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING; /** * A list of all ciphers enabled by this SSLEngine. * * This list is restricted to a list of ciphers that are supported and * approved by local policy. */ protected SSLCipher[] enabled_ciphers; /** * The minimum TLS protocol version we should attempt to handshake. * * This version is tempered by local policy, when applicable. */ protected SSLVersion min_protocol; /** * The maximum TLS protocol version we should attempt to handshake. * * This version is tempered by local policy, when applicable. */ protected SSLVersion max_protocol; /** * A JSSSession extends the SSLSession, providing useful information not * otherwise contained in the SSLSession, but exposed by NSS. */ protected JSSSession session; /** * Internal SSLFDProxy instance; useful for JSSSession support and any * custom extensions the developer wishes to support. */ protected SSLFDProxy ssl_fd; /** * Whether or not the outbound portion of this connection is closed. */ protected boolean is_outbound_closed; /** * Whether or not the inbound portion of this connection is closed. */ protected boolean is_inbound_closed; /** * Set of configuration options to enable via SSL_OptionSet(...). */ protected HashMap config; /** * Set of cached server sockets based on the PK11Cert they were * initialized with. */ protected static HashMap serverTemplates = new HashMap(); /** * Whether or not the session cache has been initialized already. * * A session cache must always be created in order to utilize a * server-side JSSEngine. However, NSS isn't threadsafe when creating * such a cache, so synchronize it within JSSEngine. */ private final static AtomicBoolean sessionCacheInitialized = new AtomicBoolean(); /** * Constructor for a JSSEngine, providing no hints for an internal * session reuse strategy and no key. * * This should always be called from an implementation's corresponding * constructor. */ public JSSEngine() { super(); session = new JSSSession(this, BUFFER_SIZE); config = getDefaultConfiguration(); } /** * Constructor for a JSSEngine, providing hints for an internal session * reuse strategy (the peer's hostname and port), but no local cert or key. * * This should always be called from an implementation's corresponding * constructor. */ public JSSEngine(String peerHost, int peerPort) { super(peerHost, peerPort); session = new JSSSession(this, BUFFER_SIZE); session.setPeerHost(peerHost); session.setPeerPort(peerPort); config = getDefaultConfiguration(); } /** * Constructor for a JSSEngine, providing hints for an internal session * reuse strategy (the peer's hostname and port), along with a chosen * certificate and key to use. * * This should always be called from an implementation's corresponding * constructor. */ public JSSEngine(String peerHost, int peerPort, org.mozilla.jss.crypto.X509Certificate localCert, org.mozilla.jss.crypto.PrivateKey localKey) { super(peerHost, peerPort); cert = (PK11Cert) localCert; key = (PK11PrivKey) localKey; session = new JSSSession(this, BUFFER_SIZE); session.setPeerHost(peerHost); session.setPeerPort(peerPort); config = getDefaultConfiguration(); } /** * Gets the error text from the NSPR layer */ protected static String errorText(int error) { // Convert the given error into a pretty string representation with // as much information as is currently available. String error_name = PR.ErrorToName(error); String error_text = PR.GetErrorText(); if (error == 0) { return "NO ERROR"; } else if (error_name.isEmpty()) { return "UNKNOWN (" + error + ")"; } else if (error_text.isEmpty()) { return error_name + " (" + error + ")"; } else { return error_name + " (" + error + "): " + error_text; } } /** * Safely initializes the session cache if not already initialized. */ public static void initializeSessionCache(int maxCacheEntries, long timeout, String directory) throws SSLException { if (sessionCacheInitialized.compareAndSet(false, true)) { if (SSL.ConfigServerSessionIDCache(maxCacheEntries, timeout, timeout, directory) == SSL.SECFailure) { String msg = "Unable to configure server session cache: "; msg += errorText(PR.GetError()); throw new SSLException(msg); } } } /** * Get the internal SSLFDProxy object; this should be preferred to * directly accessing ssl_fd. * * Note that ssl_fd can be null at various times during SSLEngine * initialization and destruction. This method should be used with * caution as callers can risk damaging the SSLEngine and making it * unusable or crash. */ public SSLFDProxy getSSLFDProxy() { return ssl_fd; } /** * Get the configuration from the current JSSEngine object as a * JSSParameters object. * * This populates the following values, when set: * - cipher suites * - protocols * - need/want client auth * - certificate alias * - peer's hostname * - ALPN protocols */ @Override public JSSParameters getSSLParameters() { JSSParameters ret = new JSSParameters(); ret.setCipherSuites(getEnabledCipherSuites()); ret.setProtocols(getEnabledProtocols()); if (getNeedClientAuth()) { ret.setNeedClientAuth(true); } else if (getWantClientAuth()) { ret.setWantClientAuth(true); } ret.setAlias(certAlias); ret.setHostname(hostname); return ret; } /** * Set the configuration from the given SSLParameters object onto this * JSSEngine. * * Aligning with the parent implementation, this calls: * - setEnabledCipherSuites when getCipherSuites is non-null, * - setEnabledProtocols when getProtocols is non-null, and * - setWantClientAuth and setNeedClientAuth. * * This doesn't yet understand from the parent implementation, the * following calls: * - getServerNames for the local server certificate selection, and * - getSNIMatchers for configuring SNI selection criteria * * Unlike the parent, this also understands: * - setCertFromAlias when getAlias is non-null, * - setHostname when getHostname is non-null. * * Note: this implementation overrides the one in SSLEngine so that we * create a JSSParameters object from the passed SSLParameters (if it is * not already an instance of JSSParameters), simplifying the other * function calls and reducing duplicate parsing. */ @Override public void setSSLParameters(SSLParameters params) { JSSParameters parsed; // Try to cast the passed parameter into a JSSParameters. This has // additional fields we usually need for construction of a NSS-backed // SSLEngine. Otherwise, parse the values into JSS-specific fields. // If we didn't create the JSSParameters here, both calls // (setEnabledCipherSuites, setEnabledProtocols) would construct their // own JSSParameters. if (params instanceof JSSParameters) { parsed = (JSSParameters) params; } else { parsed = new JSSParameters(params); } // Per semantics from parent class. if (parsed.getSSLCiphers() != null) { setEnabledCipherSuites(parsed.getSSLCiphers()); } // Per semantics from parent class. if (parsed.getSSLVersionRange() != null) { setEnabledProtocols(parsed.getSSLVersionRange()); } // Differing from the semantics of the parent class, we always set // these from the values in the parsed JSSParameters. This is because // NSS has a different set of expectations. setWantClientAuth(parsed.getWantClientAuth()); setNeedClientAuth(parsed.getNeedClientAuth()); // In the event we haven't explicitly set cert and key, try and infer // them from the alias specified... We assume that when the SSLEngine // has a certificate already, we want to use them, even if parsed has // a null certificate. if (parsed.getAlias() != null && key_managers != null && key_managers.length > 0 && cert == null && key == null) { setCertFromAlias(parsed.getAlias()); } // When we have a value for the peer hostname, we should try and use // it. if (parsed.getHostname() != null) { setHostname(parsed.getHostname()); } } /** * Set the hostname used to validate the peer's certificate. * * This is usually passed to NSS via a call to NSS's ill-named * SSL_SetURL(...), which really takes a hostname. * * Note: if this isn't called (and no peerHost was specified via a * constructor), NSS will accept any host name provided by the server! * Only useful for validating the server certificate; not used when * validating the peer's certificate. */ public void setHostname(String name) { // Note, this is the only way to set the hostname used for validation. // // In the event setHostname is never explicitly called, we should try // and fall back to the value passed in the constructor. hostname = name; } /** * Choose a certificate to give to the peer from the specified alias, * assuming KeyManagers have already been specified and at least one is * a JSSKeyManager. * * When alias is null, this clears all previous certs and keys. * * If no KeyManagers have been specified, raises an * IllegalArgumentException stating as much. * */ public void setCertFromAlias(String alias) throws IllegalArgumentException { if (alias == null) { // Per calling, semantics, get rid of any existing cert/key we // might have. certAlias = null; cert = null; key = null; return; } certAlias = alias; if (key_managers == null || key_managers.length == 0) { String msg = "Missing or null KeyManagers; refusing to search "; msg += "for cert"; throw new IllegalArgumentException(msg); } for (X509KeyManager key_manager : key_managers) { if (key_manager == null) { // Skip this key_manager. This case could occur when // setKeyManagers(...) is passed an array containing the value // null, but otherwise shouldn't happen. continue; } if (!(key_manager instanceof JSSKeyManager)) { // We're explicitly looking for a JSSKeyManager; skip this if // it doesn't match. continue; } JSSKeyManager jkm = (JSSKeyManager) key_manager; // While the return type of CryptoManager.findCertByNickname is // technically org.mozilla.jss.crypto.X509Certificate, in practice // they are always PK11Cert instances. We're going to need an // instance of PK11Cert anyways, in order to correctly pass it to // the native layer. cert = (PK11Cert) jkm.getCertificate(alias); key = (PK11PrivKey) jkm.getPrivateKey(alias); if (cert != null && key != null) { // Found a cert and key matching our alias; exit. break; } } if (cert == null && key == null) { String msg = "JSSEngine.setCertFromAlias: Unable to find "; msg += "certificate and key for specified alias!"; throw new IllegalArgumentException(msg); } } /** * Sets the list of enabled cipher suites from a list of JCA-approved * String names. * * Note: this method is slower than creating a JSSParameters configuration * object and calling setSSLParameters(...) with it. This call must * construct its own JSSParameters instance internally and translate * between JCA String names and SSLCipher instances. */ @Override public void setEnabledCipherSuites(String[] suites) throws IllegalArgumentException { JSSParameters parser = new JSSParameters(); parser.setCipherSuites(suites); setEnabledCipherSuites(parser.getSSLCiphers()); } /** * Sets the list of enabled cipher suites from a a list of SSLCipher enum * instances. */ public void setEnabledCipherSuites(SSLCipher[] suites) throws IllegalArgumentException { if (ssl_fd != null) { String msg = "Unable to process setEnabledCipherSuites(...) "; msg += "after handshake has started!"; throw new IllegalArgumentException(msg); } if (suites == null || suites.length == 0) { enabled_ciphers = null; logger.warn("JSSEngine.setEnabledCipherSuites(...) given a null list of cipher suites."); return; } ArrayList supportedCiphers = new ArrayList(); for (SSLCipher suite : suites) { if (suite.isSupported()) { supportedCiphers.add(suite); } } if (supportedCiphers.size() == 0) { enabled_ciphers = null; logger.warn("JSSEngine.setEnabledCipherSuites(...) given a list of cipher suites where none were supported or approved."); return; } enabled_ciphers = supportedCiphers.toArray(new SSLCipher[supportedCiphers.size()]); } /** * Queries the list of cipher suites enabled by default, if a * corresponding setEnabledCIpherSuites call hasn't yet been made. */ public static SSLCipher[] queryEnabledCipherSuites() { logger.debug("JSSEngine: queryEnabledCipherSuites()"); ArrayList enabledCiphers = new ArrayList(); for (SSLCipher cipher : SSLCipher.values()) { try { if (cipher.isSupported() && SSL.CipherPrefGetDefault(cipher.getID())) { logger.debug("Enabled: " + cipher.name() + " (" + cipher.getID() + ")"); enabledCiphers.add(cipher); } } catch (Exception e) { // Do nothing -- this shouldn't happen as SSLCipher should be // synced with NSS. However, we'll just log this exception as // a warning. At worst we fail to report that a cipher suite is // enabled. logger.warn("Unable to get the value of cipher: " + cipher.name() + " (" + cipher.getID() + "): " + e.getMessage()); } } return enabledCiphers.toArray(new SSLCipher[0]); } /** * Lists cipher suites currently enabled on this JSSEngine instance. */ @Override public String[] getEnabledCipherSuites() { logger.debug("JSSEngine: getEnabledCipherSuites()"); // This only happens in the event that setEnabledCipherSuites(...) // isn't called. In which case, we'll need to explicitly query the // list of default cipher suites. if (enabled_ciphers == null) { enabled_ciphers = queryEnabledCipherSuites(); } // Use JSSParameters to do the heavy lifting of converting our list // of cipher suites to an array of Strings. JSSParameters parser = new JSSParameters(); parser.setCipherSuites(enabled_ciphers); return parser.getCipherSuites(); } /** * Lists all cipher suites supported by JSS/NSS. * * Note that this list isn't just all values in SSLCipher: it is only * those which are supported and allowed by local policy. */ @Override public String[] getSupportedCipherSuites() { logger.debug("JSSEngine: getSupportedCipherSuites()"); ArrayList result = new ArrayList(); for (SSLCipher c : SSLCipher.values()) { if (c.isSupported()) { logger.debug("JSSEngine: getSupportedCipherSuites() - Supported: " + c); result.add(c.name()); } } return result.toArray(new String[result.size()]); } /** * Set the range of SSL protocols enabled by this SSLEngine instance, from * a list of JCA-standardized protocol String names. * * Note that this enables all protocols in the range of min(protocols) to * max(protocols), inclusive due to the underlying call to NSS's * SSL_VersionRangeSet(...). * * It is also recommend to construct your own JSSParameters object first * and pass it to setSSLParameters(...), rather than calling this method * directly. */ @Override public void setEnabledProtocols(String[] protocols) throws IllegalArgumentException { logger.debug("JSSEngine: setEnabledProtocols("); for (String protocol : protocols) { logger.debug("\t" + protocol + ","); } logger.debug(")"); JSSParameters parser = new JSSParameters(); parser.setProtocols(protocols); SSLVersionRange vrange = parser.getSSLVersionRange(); setEnabledProtocols(vrange); } /** * Sets the range of enabled SSL Protocols from a minimum and maximum * SSLVersion value. */ public void setEnabledProtocols(SSLVersion min, SSLVersion max) throws IllegalArgumentException { logger.debug("JSSEngine: setEnabledProtocols()"); if ((min_protocol == null && max_protocol != null) || (min_protocol != null && max_protocol == null)) { throw new IllegalArgumentException("Expected min and max to either both be null or both be not-null; not mixed: (" + min + ", " + max + ")"); } if (max == null && min == null) { min_protocol = null; max_protocol = null; return; } setEnabledProtocols(new SSLVersionRange(min, max)); } /** * Sets the range of enabled SSL Protocols from a SSLVersionRange object. */ public void setEnabledProtocols(SSLVersionRange vrange) { logger.debug("JSSEngine: setEnabledProtocols()"); if (vrange == null) { min_protocol = null; max_protocol = null; return; } if (ssl_fd != null) { String msg = "Unable to process setEnabledProtocols(...) after "; msg += "handshake has started!"; throw new IllegalArgumentException(msg); } SSLVersionRange bounded = vrange.boundBy(Policy.TLS_VERSION_RANGE); min_protocol = bounded.getMinVersion(); max_protocol = bounded.getMaxVersion(); } /** * Queries the list of protocols enabled by default. * * Only used when setEnabledProtocols(...) hasn't yet been called. */ public static SSLVersionRange queryEnabledProtocols() { logger.debug("JSSEngine: queryEnabledProtocols()"); SSLVersionRange vrange; try { vrange = SSL.VersionRangeGetDefault(); } catch (Exception e) { // This shouldn't happen unless the PRFDProxy is null. throw new RuntimeException("JSSEngine.queryEnabledProtocols() Unexpected failure: " + e.getMessage(), e); } if (vrange == null) { // Again; this shouldn't happen as the vrange should always // be created by VersionRangeGet(...). throw new RuntimeException("JSSEngine.queryEnabledProtocols() - null protocol range"); } return vrange.boundBy(Policy.TLS_VERSION_RANGE); } /** * Gets the list of enabled SSL protocol versions on this particular * JSSEngine instance, as a list of JCA-standardized strings. */ @Override public String[] getEnabledProtocols() { logger.debug("JSSEngine: getEnabledProtocols()"); if (min_protocol == null || max_protocol == null) { SSLVersionRange vrange = queryEnabledProtocols(); min_protocol = vrange.getMinVersion(); max_protocol = vrange.getMaxVersion(); } // Use JSSParameters to do the heavy lifting of converting the // SSLVersionRange to a list of JDK-conforming Strings. JSSParameters parser = new JSSParameters(); parser.setProtocols(min_protocol, max_protocol); return parser.getProtocols(); } /** * Gets the list of SSL protocols supported, as a list of JCA-standardized * strings. */ @Override public String[] getSupportedProtocols() { logger.debug("JSSEngine: getSupportedProtocols()"); ArrayList result = new ArrayList(); for (SSLVersion v : Policy.TLS_VERSION_RANGE.getAllInRange()) { logger.debug("JSSEngine: getSupportedProtocol - Supported: " + v); result.add(v.jdkAlias()); } return result.toArray(new String[result.size()]); } /** * Set public and protected key material; useful when doing client auth or * if this wasn't provided to the constructor. * * Can also be used to remove key material; however note that both * arguments must match: either both certificate and key are null or * both are not-null. */ public void setKeyMaterials(PK11Cert our_cert, PK11PrivKey our_key) throws IllegalArgumentException { logger.debug("JSSEngine: setKeyMaterials()"); if ((our_cert == null && our_key != null) || (our_cert != null && our_key == null)) { throw new IllegalArgumentException("JSSEngine.setKeyMaterials(): Either both cert and key must be null or both must be not-null"); } cert = our_cert; key = our_key; } /** * Set the internal KeyManager, when present, replacing all previous * KeyManagers. * * It is suggested that at least one key manager be a JSSKeyManager * instance if a key and certificate must be provided for this end of * the connection. */ public void setKeyManager(X509KeyManager km) { if (km == null) { logger.debug("JSSEngine: setKeyManager(null)"); return; } logger.debug("JSSEngine: setKeyManager(" + km.getClass().getName() + ")"); key_managers = new X509KeyManager[] { km }; } /** * Set the internal list of KeyManagers. * * It is suggested that at least one key manager be a JSSKeyManager * instance if a key and certificate must be provided for this end of * the connection. */ public void setKeyManagers(X509KeyManager[] xkms) { if (xkms == null) { logger.debug("JSSEngine: setKeyManagers([null])"); return; } logger.debug("JSSEngine: setKeyManagers("); for (X509KeyManager km : xkms) { logger.debug(" - " + km.getClass().getName()); } logger.debug(")"); key_managers = xkms; } /** * Set the internal TrustManager, when present, replacing all previous * TrustManagers. */ public void setTrustManager(JSSTrustManager tm) { if (tm == null) { logger.debug("JSSEngine: setTrustManager(null)"); return; } logger.debug("JSSEngine: setTrustManager(" + tm.getClass().getName() + ")"); trust_managers = new X509TrustManager[] { tm }; } /** * Set the internal list of TrustManagers. */ public void setTrustManagers(X509TrustManager[] xtms) { if (xtms == null) { logger.debug("JSSEngine: setKeyManagers([null])"); return; } logger.debug("JSSEngine: setTrustManagers("); for (X509TrustManager tm : xtms) { logger.debug(" - " + tm.getClass().getName()); } logger.debug(")"); trust_managers = xtms; } /** * Gets the JSSSession object which reflects the status of this * JSS Engine's session. */ @Override public JSSSession getSession() { logger.debug("JSSEngine: getSession()"); return session; } /** * Whether or not to enable this SSLEngine instance to create new * sessions. * * The default value is true. When passed the value false, this will * throw a RuntimeException, stating that all JSS Engines do not support * restricting to only resuming existing sessions. */ @Override public void setEnableSessionCreation(boolean flag) { logger.debug("JSSEngine: setEnableSessionCreation(" + flag + ") - not implemented"); if (!flag) { String msg = "JSSEngine does not support restricting to only resuming existing sessions."; throw new RuntimeException(msg); } } /** * Whether or not new sessions can be created by this SSLEngine instance. * * This always returns true. */ @Override public boolean getEnableSessionCreation() { logger.debug("JSSEngine: getEnableSessionCreation() - not implemented"); return true; } /** * Set whether or not to handshake as a client. */ @Override public void setUseClientMode(boolean mode) throws IllegalArgumentException { logger.debug("JSSEngine.setUseClientMode(" + mode + ")"); if (ssl_fd != null) { String msg = "Unable to process setUseClientMode(" + mode + ") "; msg += "after handshake has started!"; throw new IllegalArgumentException(msg); } as_server = !mode; } /** * Set whether or not client authentication is required for the TLS * handshake to succeed. */ @Override public void setNeedClientAuth(boolean need) { logger.debug("JSSEngine.setNeedClientAuth(" + need + ")"); need_client_auth = need; reconfigureClientAuth(); } /** * Set whether or not we should attempt client authentication. */ @Override public void setWantClientAuth(boolean want) { logger.debug("JSSEngine.setWantClientAuth(" + want + ")"); want_client_auth = want; reconfigureClientAuth(); } /** * Implementation-specific handler to handle reconfiguration of client * authentication after the handshake has completed. * * Note that this always gets called, regardless of if the handshake has * started; it is up to the implementation to handle this appropriately. */ protected abstract void reconfigureClientAuth(); /** * Query whether this JSSEngine is a client (true) or a server (false). */ @Override public boolean getUseClientMode() { return !as_server; } /** * Query whether or not we must have client authentication for the TLS * handshake to succeed. */ @Override public boolean getNeedClientAuth() { return need_client_auth; } /** * Query whether or not we request client authentication. */ @Override public boolean getWantClientAuth() { return want_client_auth; } /** * Query whether or not the inbound side of this connection is closed. */ @Override public boolean isInboundDone() { logger.debug("JSSEngine.isInboundDone()? " + is_inbound_closed); return is_inbound_closed; } /** * Query whether or not the outbound side of this connection is closed. */ @Override public boolean isOutboundDone() { logger.debug("JSSEngine.isOutboundDone()? " + is_outbound_closed); return is_outbound_closed; } /** * Gets the current security status of this JSSEngine instance. * * This is abstract to allow implementations to implement this (and step * their handshake mechanism) as they wish. */ public abstract SecurityStatusResult getStatus(); /** * Gets the default configuration. */ public HashMap getDefaultConfiguration() { HashMap result = new HashMap(); // JSS (and NSS) generally supports post-handshake authentication, but // we might not always have key material up front. Set the extension // anyways, to give the JSSEngine the chance to negotiate it in the // future. result.put(SSL.ENABLE_POST_HANDSHAKE_AUTH, 1); // Allow (and enable) only secure renegotiation. Only relevant for // TLS < 1.3. result.put(SSL.ENABLE_RENEGOTIATION, SSL.RENEGOTIATE_REQUIRES_XTN); result.put(SSL.REQUIRE_SAFE_NEGOTIATION, 1); // Don't enable FALLBACK_SCSV support; this is incompatible with other // JCA providers and makes transitioning TLS versions difficult. // result.put(SSL.ENABLE_FALLBACK_SCSV, 1); return result; } /** * Updates the configuration with the given value. */ public void addConfiguration(int key, int value) { config.put(key, value); } /** * Removes the given key from the configuration. */ public void removeConfiguration(int key) { config.remove(key); } /** * Sets the configuration, replacing all current values. */ public void setConfiguration(HashMap config) { this.config = config; } /** * Returns the templated server certificate, if one exists. */ protected static SSLFDProxy getServerTemplate(PK11Cert cert, PK11PrivKey key) { if (cert == null || key == null) { return null; } SSLFDProxy fd = serverTemplates.get(cert); if (fd == null) { PRFDProxy base = PR.NewTCPSocket(); fd = SSL.ImportFD(null, base); if (SSL.ConfigServerCert(fd, cert, key) != SSL.SECSuccess) { String msg = "Unable to configure certificate and key on "; msg += "model SSL PRFileDesc proxy: "; msg += errorText(PR.GetError()); throw new RuntimeException(msg); } serverTemplates.put(cert, fd); } return fd; } /** * Calls cleanup only if both inbound and outbound data streams are * closed. * * This prevents accidental cleanup in the case of a partially open * connection. */ public abstract void tryCleanup(); /** * Performs cleanup of internal data, closing both inbound and outbound * data streams if still open. */ public abstract void cleanup(); } jss-5.0.0/src/main/java/org/mozilla/jss/ssl/javax/JSSEngineReferenceImpl.java000066400000000000000000002236141412550063600270210ustar00rootroot00000000000000package org.mozilla.jss.ssl.javax; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.nio.channels.WritableByteChannel; import java.nio.channels.Channels; import java.security.PublicKey; import java.nio.ByteBuffer; import javax.net.ssl.*; import org.mozilla.jss.nss.*; import org.mozilla.jss.pkcs11.*; import org.mozilla.jss.provider.javax.crypto.*; import org.mozilla.jss.ssl.*; /** * The reference JSSEngine implementation. * * This JSSEngine implementation is a reference for future JSSEngine * implementations, providing a pure-Java overview of what should happen at * each step of the init, wrap, and unwrap calls. * * This implementation allows for extended debug logging, but also debug * packet logging. The latter writes out packets sent via wrap(...) and * received from unwrap(...) to a port on localhost. This allows one to easily * attach Wireshark or tcpdump and inspect the TLS packets, even if errors * occur during the test suite (where packets aren't sent over the wire by * default). This maintains the client/server relationship, and are logged * as being from the appropriate side of the TLS connection. */ public class JSSEngineReferenceImpl extends JSSEngine { /** * Faked peer information that we pass to the underlying BufferPRFD * implementation. * * This is used by NSS for session resumption. However, because we * don't have the exact peer information at the JSSEngine level, at * best we can guess. */ private String peer_info; /** * Whether or not the underlying ssl_fd is closed or not. * * Because the socket isn't open yet, we set it to true, to indicate * that no data can be sent or received. */ private boolean closed_fd = true; /** * Data to be read by the NSS SSL implementation; data from the peer. */ private BufferProxy read_buf; /** * Data written by the NSS SSL implementation; data sent to the peer. */ private BufferProxy write_buf; /** * Number of times heuristic has not matched the current state. * * Because this JSSEngine uses a heuristic for determining when the * handshake is completed (or, when we need to switch from WRAP to * UNWRAP), and the heuristic is sometimes wrong, we track how many * times it is in an unknown state. When we hit some internal * threshold, we swap states. */ private int unknown_state_count; /** * Whether or not to step the handshake. */ private boolean step_handshake; /** * Whether or not a FINISHED handshake status has been returned to our * caller. * * Because this JSSEngine implementation re-enters the * updateHandshakeState() method potentially multiple times during a * single call to wrap() or unwrap(), we need to know whether or not * the top-level call has returned a FINISHED result. If it hasn't, * we want to keep the state on FINISHED until it has been returned, * otherwise we'll skip straight to NOT_HANDSHAKING, confusing our * peer. */ private boolean returned_finished; /** * Value of the SSLException we've encountered. */ private SSLException ssl_exception; /** * Whether or not we've seen an ssl exception. * * Note that, when the exception ultimately gets thrown to the caller, * ssl_exception will be NULLed; this tracks whether or not the connection * has failed previously for some reason. */ private boolean seen_exception; // In this reference implementation, we allow logging of (encrypted) data // to a Socket for ease of testing. By default, this socket is disabled. private int debug_port; private ServerSocket ss_socket; private Socket s_socket; private Socket c_socket; private InputStream s_istream; private OutputStream s_ostream; private InputStream c_istream; private OutputStream c_ostream; /** * Internal name for this JSSEngine instance; most commonly used during * testing. */ private String name; /** * Automatically generated prefix for debug information. */ private String prefix = ""; /** * Runnable task; this performs certificate validation against user-provided * TrustManager instances, passing the result back to NSS. */ private CertValidationTask task; public JSSEngineReferenceImpl() { super(); // We were given no hints about our peer so we have no information // to signal to NSS for session resumption. peer_info = null; debug("JSSEngine: constructor()"); } public JSSEngineReferenceImpl(String peerHost, int peerPort) { super(peerHost, peerPort); // Signal host and port for session resumption. Only do it when we've // been given valid information. if (peerHost != null && peerPort != 0) { peer_info = peerHost + ":" + peerPort; } // Massive hack for compatibility. In particular, Java usually // specifies the peer information here. NSS uses SSL_SetURL not only // for hostname verification, but also for SNI (!!) on the client. // This means that there's no way to indicate (to those servers like // google.com which require SNI) hostname for the client WITHOUT // also validating the hostname at certificate verification time. // Because the certificate hostname explicitly isn't provided (per // JCA specification) for validation, this might break other clients // which don't provide this information. However, the alternative is // that we never add SNI indication, ever. // // Specifically, this breaks a dead-simple Apache HTTP Components // client: // // CloseableHttpClient client = HttpClients.createDefault(); // HttpGet request = new HttpGet("https://google.com/"); // HttpResponse response = client.execute(request); // System.out.println(response); // // Without this, we have no way for the above to work. setHostname(peerHost); debug("JSSEngine: constructor(" + peerHost + ", " + peerPort + ")"); } public JSSEngineReferenceImpl(String peerHost, int peerPort, org.mozilla.jss.crypto.X509Certificate localCert, org.mozilla.jss.crypto.PrivateKey localKey) { super(peerHost, peerPort, localCert, localKey); // Signal host and port for session resumption. Only do it when we've // been given valid information. if (peerHost != null && peerPort != 0) { peer_info = peerHost + ":" + peerPort; } // See above. setHostname(peerHost); prefix = prefix + "[" + peer_info + "] "; debug("JSSEngine: constructor(" + peerHost + ", " + peerPort + ", " + localCert + ", " + localKey + ")"); } private void debug(String msg) { logger.debug(prefix + msg); } private void info(String msg) { logger.info(prefix + msg); } private void warn(String msg) { logger.warn(prefix + msg); } /** * Set the name of this JSSEngine instance, to be printed in logging calls. * * This helps when debugging output from multiple JSSEngine instances at * the same time, such as within the JSS test suite. */ public void setName(String name) { this.name = name; prefix = "[" + this.name + "] " + prefix; } private void init() throws SSLException { debug("JSSEngine: init()"); // Initialize our JSSEngine when we begin to handshake; otherwise, // calls to Set

 * try (NEC obj = new NEC(...)) {
 *      // ... do something with obj ...
 * }
 * 
* * Extending classes implement acquireNativeResources() and * releaseNativeResources(). Before this instance is passed to the JNI layer, * open() should be called, allocating all necessary resources. After making * all necessary JNI calls, close() should be called to free resources. * Ideally, open() and close() should be called close to the JNI calls, * wrapped by the developer to limit accidental memory leaks. */ public abstract class NativeEnclosure implements AutoCloseable { /** * Enclosed NativeProxy reference. */ public NativeProxy mPointer; /** * Size of enclosed mPointer. */ public long mPointerSize; /** * Allocate and initialize mPointer with its enclosed value. * * Note that this method prevents you from accidentally leaking memory; * to call open() twice, call close() first. */ public final void open() throws Exception { if (mPointer == null) { acquireNativeResources(); } } @Override @Deprecated protected void finalize() throws Throwable { close(); } /** * Deinitialize and free mPointer. * * Must be called to prevent memory leaks. */ @Override public final void close() throws Exception { if (mPointer != null) { releaseNativeResources(); mPointer.close(); } mPointer = null; mPointerSize = 0; } /** * Allocate native resources, setting mPointer and mPointerSize as * appropriate. */ protected abstract void acquireNativeResources() throws Exception; /** * Called to deallocate native resources; note that mPointer.close() * is called afterwards. * * If mPointer.close() should be a no-op, extend from StaticVoidRef and * do any required cleanup here. */ protected abstract void releaseNativeResources() throws Exception; } jss-5.0.0/src/main/java/org/mozilla/jss/util/NativeErrcodes.c000066400000000000000000000347751412550063600240640ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include typedef struct { PRErrorCode native; int java; } Errcode; /* * This table correlates NSPR and NSS error codes to the enums defined * in o.m.util.NativeErrcodes. It must be kept in sync with that class. */ static Errcode errcodeTable[] = { {PR_OUT_OF_MEMORY_ERROR, 1}, {PR_BAD_DESCRIPTOR_ERROR, 2}, {PR_WOULD_BLOCK_ERROR, 3}, {PR_ACCESS_FAULT_ERROR, 4}, {PR_INVALID_METHOD_ERROR, 5}, {PR_ILLEGAL_ACCESS_ERROR, 6}, {PR_UNKNOWN_ERROR, 7}, {PR_PENDING_INTERRUPT_ERROR, 8}, {PR_NOT_IMPLEMENTED_ERROR, 9}, {PR_IO_ERROR, 10}, {PR_IO_TIMEOUT_ERROR, 11}, {PR_IO_PENDING_ERROR, 12}, {PR_DIRECTORY_OPEN_ERROR, 13}, {PR_INVALID_ARGUMENT_ERROR, 14}, {PR_ADDRESS_NOT_AVAILABLE_ERROR, 15}, {PR_ADDRESS_NOT_SUPPORTED_ERROR, 16}, {PR_IS_CONNECTED_ERROR, 17}, {PR_BAD_ADDRESS_ERROR, 18}, {PR_ADDRESS_IN_USE_ERROR, 19}, {PR_CONNECT_REFUSED_ERROR, 20}, {PR_NETWORK_UNREACHABLE_ERROR, 21}, {PR_CONNECT_TIMEOUT_ERROR, 22}, {PR_NOT_CONNECTED_ERROR, 23}, {PR_LOAD_LIBRARY_ERROR, 24}, {PR_UNLOAD_LIBRARY_ERROR, 25}, {PR_FIND_SYMBOL_ERROR, 26}, {PR_INSUFFICIENT_RESOURCES_ERROR, 27}, {PR_DIRECTORY_LOOKUP_ERROR, 28}, {PR_TPD_RANGE_ERROR, 29}, {PR_PROC_DESC_TABLE_FULL_ERROR, 30}, {PR_SYS_DESC_TABLE_FULL_ERROR, 31}, {PR_NOT_SOCKET_ERROR, 32}, {PR_NOT_TCP_SOCKET_ERROR, 33}, {PR_SOCKET_ADDRESS_IS_BOUND_ERROR, 34}, {PR_NO_ACCESS_RIGHTS_ERROR, 35}, {PR_OPERATION_NOT_SUPPORTED_ERROR, 36}, {PR_PROTOCOL_NOT_SUPPORTED_ERROR, 37}, {PR_REMOTE_FILE_ERROR, 38}, {PR_BUFFER_OVERFLOW_ERROR, 39}, {PR_CONNECT_RESET_ERROR, 40}, {PR_RANGE_ERROR, 41}, {PR_DEADLOCK_ERROR, 42}, {PR_FILE_IS_LOCKED_ERROR, 43}, {PR_FILE_TOO_BIG_ERROR, 44}, {PR_NO_DEVICE_SPACE_ERROR, 45}, {PR_PIPE_ERROR, 46}, {PR_NO_SEEK_DEVICE_ERROR, 47}, {PR_IS_DIRECTORY_ERROR, 48}, {PR_LOOP_ERROR, 49}, {PR_NAME_TOO_LONG_ERROR, 50}, {PR_FILE_NOT_FOUND_ERROR, 51}, {PR_NOT_DIRECTORY_ERROR, 52}, {PR_READ_ONLY_FILESYSTEM_ERROR, 53}, {PR_DIRECTORY_NOT_EMPTY_ERROR, 54}, {PR_FILESYSTEM_MOUNTED_ERROR, 55}, {PR_NOT_SAME_DEVICE_ERROR, 56}, {PR_DIRECTORY_CORRUPTED_ERROR, 57}, {PR_FILE_EXISTS_ERROR, 58}, {PR_MAX_DIRECTORY_ENTRIES_ERROR, 59}, {PR_INVALID_DEVICE_STATE_ERROR, 60}, {PR_DEVICE_IS_LOCKED_ERROR, 61}, {PR_NO_MORE_FILES_ERROR, 62}, {PR_END_OF_FILE_ERROR, 63}, {PR_FILE_SEEK_ERROR, 64}, {PR_FILE_IS_BUSY_ERROR, 65}, {PR_OPERATION_ABORTED_ERROR, 66}, {PR_IN_PROGRESS_ERROR, 67}, {PR_ALREADY_INITIATED_ERROR, 68}, {PR_GROUP_EMPTY_ERROR, 69}, {PR_INVALID_STATE_ERROR, 70}, {PR_NETWORK_DOWN_ERROR, 71}, {PR_SOCKET_SHUTDOWN_ERROR, 72}, {PR_CONNECT_ABORTED_ERROR, 73}, {PR_HOST_UNREACHABLE_ERROR, 74}, {SSL_ERROR_BASE, 77}, {SSL_ERROR_EXPORT_ONLY_SERVER, 78}, {SSL_ERROR_US_ONLY_SERVER, 79}, {SSL_ERROR_NO_CYPHER_OVERLAP, 80}, {SSL_ERROR_NO_CERTIFICATE, 81}, {SSL_ERROR_BAD_CERTIFICATE, 82}, {SSL_ERROR_BAD_CLIENT, 83}, {SSL_ERROR_BAD_SERVER, 84}, {SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE, 85}, {SSL_ERROR_UNSUPPORTED_VERSION, 86}, {SSL_ERROR_WRONG_CERTIFICATE, 87}, {SSL_ERROR_BAD_CERT_DOMAIN, 88}, {SSL_ERROR_POST_WARNING, 89}, {SSL_ERROR_SSL2_DISABLED, 90}, {SSL_ERROR_BAD_MAC_READ, 91}, {SSL_ERROR_BAD_MAC_ALERT, 92}, {SSL_ERROR_BAD_CERT_ALERT, 93}, {SSL_ERROR_REVOKED_CERT_ALERT, 94}, {SSL_ERROR_EXPIRED_CERT_ALERT, 95}, {SSL_ERROR_SSL_DISABLED, 96}, {SSL_ERROR_FORTEZZA_PQG, 97}, {SSL_ERROR_UNKNOWN_CIPHER_SUITE, 98}, {SSL_ERROR_NO_CIPHERS_SUPPORTED, 99}, {SSL_ERROR_BAD_BLOCK_PADDING, 100}, {SSL_ERROR_RX_RECORD_TOO_LONG, 101}, {SSL_ERROR_TX_RECORD_TOO_LONG, 102}, {SSL_ERROR_RX_MALFORMED_HELLO_REQUEST, 103}, {SSL_ERROR_RX_MALFORMED_CLIENT_HELLO, 104}, {SSL_ERROR_RX_MALFORMED_SERVER_HELLO, 105}, {SSL_ERROR_RX_MALFORMED_CERTIFICATE, 106}, {SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH, 107}, {SSL_ERROR_RX_MALFORMED_CERT_REQUEST, 108}, {SSL_ERROR_RX_MALFORMED_HELLO_DONE, 109}, {SSL_ERROR_RX_MALFORMED_CERT_VERIFY, 110}, {SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH, 111}, {SSL_ERROR_RX_MALFORMED_FINISHED, 112}, {SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER, 113}, {SSL_ERROR_RX_MALFORMED_ALERT, 114}, {SSL_ERROR_RX_MALFORMED_HANDSHAKE, 115}, {SSL_ERROR_RX_MALFORMED_APPLICATION_DATA, 116}, {SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST, 117}, {SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO, 118}, {SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO, 119}, {SSL_ERROR_RX_UNEXPECTED_CERTIFICATE, 120}, {SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH, 121}, {SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST, 122}, {SSL_ERROR_RX_UNEXPECTED_HELLO_DONE, 123}, {SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY, 124}, {SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH, 125}, {SSL_ERROR_RX_UNEXPECTED_FINISHED, 126}, {SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER, 127}, {SSL_ERROR_RX_UNEXPECTED_ALERT, 128}, {SSL_ERROR_RX_UNEXPECTED_HANDSHAKE, 129}, {SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA, 130}, {SSL_ERROR_RX_UNKNOWN_RECORD_TYPE, 131}, {SSL_ERROR_RX_UNKNOWN_HANDSHAKE, 132}, {SSL_ERROR_RX_UNKNOWN_ALERT, 133}, {SSL_ERROR_CLOSE_NOTIFY_ALERT, 134}, {SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT, 135}, {SSL_ERROR_DECOMPRESSION_FAILURE_ALERT, 136}, {SSL_ERROR_HANDSHAKE_FAILURE_ALERT, 137}, {SSL_ERROR_ILLEGAL_PARAMETER_ALERT, 138}, {SSL_ERROR_UNSUPPORTED_CERT_ALERT, 139}, {SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT, 140}, {SSL_ERROR_GENERATE_RANDOM_FAILURE, 141}, {SSL_ERROR_SIGN_HASHES_FAILURE, 142}, {SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE, 143}, {SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE, 144}, {SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE, 145}, {SSL_ERROR_ENCRYPTION_FAILURE, 146}, {SSL_ERROR_DECRYPTION_FAILURE, 147}, {SSL_ERROR_SOCKET_WRITE_FAILURE, 148}, {SSL_ERROR_MD5_DIGEST_FAILURE, 149}, {SSL_ERROR_SHA_DIGEST_FAILURE, 150}, {SSL_ERROR_MAC_COMPUTATION_FAILURE, 151}, {SSL_ERROR_SYM_KEY_CONTEXT_FAILURE, 152}, {SSL_ERROR_SYM_KEY_UNWRAP_FAILURE, 153}, {SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED, 154}, {SSL_ERROR_IV_PARAM_FAILURE, 155}, {SSL_ERROR_INIT_CIPHER_SUITE_FAILURE, 156}, {SSL_ERROR_SESSION_KEY_GEN_FAILURE, 157}, {SSL_ERROR_NO_SERVER_KEY_FOR_ALG, 158}, {SSL_ERROR_TOKEN_INSERTION_REMOVAL, 159}, {SSL_ERROR_TOKEN_SLOT_NOT_FOUND, 160}, {SSL_ERROR_NO_COMPRESSION_OVERLAP, 161}, {SSL_ERROR_HANDSHAKE_NOT_COMPLETED, 162}, {SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE, 163}, {SSL_ERROR_CERT_KEA_MISMATCH, 164}, {SSL_ERROR_NO_TRUSTED_SSL_CLIENT_CA, 165}, {SSL_ERROR_SESSION_NOT_FOUND, 166}, {SSL_ERROR_DECRYPTION_FAILED_ALERT, 167}, {SSL_ERROR_RECORD_OVERFLOW_ALERT, 168}, {SSL_ERROR_UNKNOWN_CA_ALERT, 169}, {SSL_ERROR_ACCESS_DENIED_ALERT, 170}, {SSL_ERROR_DECODE_ERROR_ALERT, 171}, {SSL_ERROR_DECRYPT_ERROR_ALERT, 172}, {SSL_ERROR_EXPORT_RESTRICTION_ALERT, 173}, {SSL_ERROR_PROTOCOL_VERSION_ALERT, 174}, {SSL_ERROR_INSUFFICIENT_SECURITY_ALERT, 175}, {SSL_ERROR_INTERNAL_ERROR_ALERT, 176}, {SSL_ERROR_USER_CANCELED_ALERT, 177}, {SSL_ERROR_NO_RENEGOTIATION_ALERT, 178}, {SEC_ERROR_IO, 179}, {SEC_ERROR_LIBRARY_FAILURE, 180}, {SEC_ERROR_BAD_DATA, 181}, {SEC_ERROR_OUTPUT_LEN, 182}, {SEC_ERROR_INPUT_LEN, 183}, {SEC_ERROR_INVALID_ARGS, 184}, {SEC_ERROR_INVALID_ALGORITHM, 185}, {SEC_ERROR_INVALID_AVA, 186}, {SEC_ERROR_INVALID_TIME, 187}, {SEC_ERROR_BAD_DER, 188}, {SEC_ERROR_BAD_SIGNATURE, 189}, {SEC_ERROR_EXPIRED_CERTIFICATE, 190}, {SEC_ERROR_REVOKED_CERTIFICATE, 191}, {SEC_ERROR_UNKNOWN_ISSUER, 192}, {SEC_ERROR_BAD_KEY, 193}, {SEC_ERROR_BAD_PASSWORD, 194}, {SEC_ERROR_RETRY_PASSWORD, 195}, {SEC_ERROR_NO_NODELOCK, 196}, {SEC_ERROR_BAD_DATABASE, 197}, {SEC_ERROR_NO_MEMORY, 198}, {SEC_ERROR_UNTRUSTED_ISSUER, 199}, {SEC_ERROR_UNTRUSTED_CERT, 200}, {SEC_ERROR_DUPLICATE_CERT, 201}, {SEC_ERROR_DUPLICATE_CERT_NAME, 202}, {SEC_ERROR_ADDING_CERT, 203}, {SEC_ERROR_FILING_KEY, 204}, {SEC_ERROR_NO_KEY, 205}, {SEC_ERROR_CERT_VALID, 206}, {SEC_ERROR_CERT_NOT_VALID, 207}, {SEC_ERROR_CERT_NO_RESPONSE, 208}, {SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE, 209}, {SEC_ERROR_CRL_EXPIRED, 210}, {SEC_ERROR_CRL_BAD_SIGNATURE, 211}, {SEC_ERROR_CRL_INVALID, 212}, {SEC_ERROR_EXTENSION_VALUE_INVALID, 213}, {SEC_ERROR_EXTENSION_NOT_FOUND, 214}, {SEC_ERROR_CA_CERT_INVALID, 215}, {SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID, 216}, {SEC_ERROR_CERT_USAGES_INVALID, 217}, {SEC_INTERNAL_ONLY, 218}, {SEC_ERROR_INVALID_KEY, 219}, {SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION, 220}, {SEC_ERROR_OLD_CRL, 221}, {SEC_ERROR_NO_EMAIL_CERT, 222}, {SEC_ERROR_NO_RECIPIENT_CERTS_QUERY, 223}, {SEC_ERROR_NOT_A_RECIPIENT, 224}, {SEC_ERROR_PKCS7_KEYALG_MISMATCH, 225}, {SEC_ERROR_PKCS7_BAD_SIGNATURE, 226}, {SEC_ERROR_UNSUPPORTED_KEYALG, 227}, {SEC_ERROR_DECRYPTION_DISALLOWED, 228}, {XP_SEC_FORTEZZA_BAD_CARD, 229}, {XP_SEC_FORTEZZA_NO_CARD, 230}, {XP_SEC_FORTEZZA_NONE_SELECTED, 231}, {XP_SEC_FORTEZZA_MORE_INFO, 232}, {XP_SEC_FORTEZZA_PERSON_NOT_FOUND, 233}, {XP_SEC_FORTEZZA_NO_MORE_INFO, 234}, {XP_SEC_FORTEZZA_BAD_PIN, 235}, {XP_SEC_FORTEZZA_PERSON_ERROR, 236}, {SEC_ERROR_NO_KRL, 237}, {SEC_ERROR_KRL_EXPIRED, 238}, {SEC_ERROR_KRL_BAD_SIGNATURE, 239}, {SEC_ERROR_REVOKED_KEY, 240}, {SEC_ERROR_KRL_INVALID, 241}, {SEC_ERROR_NEED_RANDOM, 242}, {SEC_ERROR_NO_MODULE, 243}, {SEC_ERROR_NO_TOKEN, 244}, {SEC_ERROR_READ_ONLY, 245}, {SEC_ERROR_NO_SLOT_SELECTED, 246}, {SEC_ERROR_CERT_NICKNAME_COLLISION, 247}, {SEC_ERROR_KEY_NICKNAME_COLLISION, 248}, {SEC_ERROR_SAFE_NOT_CREATED, 249}, {SEC_ERROR_BAGGAGE_NOT_CREATED, 250}, {XP_JAVA_REMOVE_PRINCIPAL_ERROR, 251}, {XP_JAVA_DELETE_PRIVILEGE_ERROR, 252}, {XP_JAVA_CERT_NOT_EXISTS_ERROR, 253}, {SEC_ERROR_BAD_EXPORT_ALGORITHM, 254}, {SEC_ERROR_EXPORTING_CERTIFICATES, 255}, {SEC_ERROR_IMPORTING_CERTIFICATES, 256}, {SEC_ERROR_PKCS12_DECODING_PFX, 257}, {SEC_ERROR_PKCS12_INVALID_MAC, 258}, {SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM, 259}, {SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE, 260}, {SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE, 261}, {SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM, 262}, {SEC_ERROR_PKCS12_UNSUPPORTED_VERSION, 263}, {SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT, 264}, {SEC_ERROR_PKCS12_CERT_COLLISION, 265}, {SEC_ERROR_USER_CANCELLED, 266}, {SEC_ERROR_PKCS12_DUPLICATE_DATA, 267}, {SEC_ERROR_MESSAGE_SEND_ABORTED, 268}, {SEC_ERROR_INADEQUATE_KEY_USAGE, 269}, {SEC_ERROR_INADEQUATE_CERT_TYPE, 270}, {SEC_ERROR_CERT_ADDR_MISMATCH, 271}, {SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY, 272}, {SEC_ERROR_PKCS12_IMPORTING_CERT_CHAIN, 273}, {SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME, 274}, {SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY, 275}, {SEC_ERROR_PKCS12_UNABLE_TO_WRITE, 276}, {SEC_ERROR_PKCS12_UNABLE_TO_READ, 277}, {SEC_ERROR_PKCS12_KEY_DATABASE_NOT_INITIALIZED, 278}, {SEC_ERROR_KEYGEN_FAIL, 279}, {SEC_ERROR_INVALID_PASSWORD, 280}, {SEC_ERROR_RETRY_OLD_PASSWORD, 281}, {SEC_ERROR_BAD_NICKNAME, 282}, {SEC_ERROR_NOT_FORTEZZA_ISSUER, 283}, {SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY, 284}, {SEC_ERROR_JS_INVALID_MODULE_NAME, 285}, {SEC_ERROR_JS_INVALID_DLL, 286}, {SEC_ERROR_JS_ADD_MOD_FAILURE, 287}, {SEC_ERROR_JS_DEL_MOD_FAILURE, 288}, {SEC_ERROR_OLD_KRL, 289}, {SEC_ERROR_CKL_CONFLICT, 290}, {SEC_ERROR_CERT_NOT_IN_NAME_SPACE, 291}, {SEC_ERROR_KRL_NOT_YET_VALID, 292}, {SEC_ERROR_CRL_NOT_YET_VALID, 293}, {SEC_ERROR_UNKNOWN_CERT, 294}, {SEC_ERROR_UNKNOWN_SIGNER, 295}, {SEC_ERROR_CERT_BAD_ACCESS_LOCATION, 296}, {SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE, 297}, {SEC_ERROR_OCSP_BAD_HTTP_RESPONSE, 298}, {SEC_ERROR_OCSP_MALFORMED_REQUEST, 299}, {SEC_ERROR_OCSP_SERVER_ERROR, 300}, {SEC_ERROR_OCSP_TRY_SERVER_LATER, 301}, {SEC_ERROR_OCSP_REQUEST_NEEDS_SIG, 302}, {SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST, 303}, {SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, 304}, {SEC_ERROR_OCSP_UNKNOWN_CERT, 305}, {SEC_ERROR_OCSP_NOT_ENABLED, 306}, {SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER, 307}, {SEC_ERROR_OCSP_MALFORMED_RESPONSE, 308}, {SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE, 309}, {SEC_ERROR_OCSP_FUTURE_RESPONSE, 310}, {SEC_ERROR_OCSP_OLD_RESPONSE, 311}, {SEC_ERROR_DIGEST_NOT_FOUND, 312}, {SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE, 313} }; #define numErrcodes (sizeof(errcodeTable)/sizeof(Errcode)) static int errcodeCompare(const void *elem1, const void *elem2) { Errcode *ec1, *ec2; ec1 = (Errcode*) elem1; ec2 = (Errcode*) elem2; if( ec1->native < ec2->native ) { return -1; } else if( ec1->native == ec2->native ) { return 0; } else { /* ec1->native > ec2->native */ return 1; } } #ifdef DEBUG static int initialized = 0; #endif /************************************************************************ ** ** J S S _ i n i t E r r c o d e T r a n s l a t i o n T a b l e. ** ** Initializes the error code translation table. This should be called ** by CryptoManager.initialize(), and must be called before any calls to ** JSS_ConvertNativeErrcodeToJava. ** */ void JSS_initErrcodeTranslationTable() { /* sort the table by native errcode */ qsort(errcodeTable, numErrcodes, sizeof(Errcode), errcodeCompare); #ifdef DEBUG initialized = 1; #endif } /************************************************************************ ** ** J S S _ C o n v e r t N a t i v e E r r c o d e T o J a v a ** ** Converts an NSPR or NSS error code to a Java error code. ** (defined in the class o.m.util.NativeErrcodes) ** ** Returns ** The Java error code, or -1 if a corresponding Java error code could ** not be found. */ int JSS_ConvertNativeErrcodeToJava(PRErrorCode nativeErrcode) { Errcode key; Errcode *target; #ifdef DEBUG PR_ASSERT(initialized); #endif key.native = nativeErrcode; key.java = -1; target = bsearch( &key, errcodeTable, numErrcodes, sizeof(Errcode), errcodeCompare ); if( target == NULL ) { return -1; } else { return target->java; } } jss-5.0.0/src/main/java/org/mozilla/jss/util/NativeErrcodes.java000066400000000000000000000512351412550063600245510ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.util; /** * An enumeration of all error codes from NSS and NSPR. * The integer values associated with each error code are subject to change, so * DO NOT DEPEND ON THEM. Only use the symbolic names. */ public class NativeErrcodes { public static final int PR_OUT_OF_MEMORY_ERROR = 1; public static final int PR_BAD_DESCRIPTOR_ERROR = 2; public static final int PR_WOULD_BLOCK_ERROR = 3; public static final int PR_ACCESS_FAULT_ERROR = 4; public static final int PR_INVALID_METHOD_ERROR = 5; public static final int PR_ILLEGAL_ACCESS_ERROR = 6; public static final int PR_UNKNOWN_ERROR = 7; public static final int PR_PENDING_INTERRUPT_ERROR = 8; public static final int PR_NOT_IMPLEMENTED_ERROR = 9; public static final int PR_IO_ERROR = 10; public static final int PR_IO_TIMEOUT_ERROR = 11; public static final int PR_IO_PENDING_ERROR = 12; public static final int PR_DIRECTORY_OPEN_ERROR = 13; public static final int PR_INVALID_ARGUMENT_ERROR = 14; public static final int PR_ADDRESS_NOT_AVAILABLE_ERROR = 15; public static final int PR_ADDRESS_NOT_SUPPORTED_ERROR = 16; public static final int PR_IS_CONNECTED_ERROR = 17; public static final int PR_BAD_ADDRESS_ERROR = 18; public static final int PR_ADDRESS_IN_USE_ERROR = 19; public static final int PR_CONNECT_REFUSED_ERROR = 20; public static final int PR_NETWORK_UNREACHABLE_ERROR = 21; public static final int PR_CONNECT_TIMEOUT_ERROR = 22; public static final int PR_NOT_CONNECTED_ERROR = 23; public static final int PR_LOAD_LIBRARY_ERROR = 24; public static final int PR_UNLOAD_LIBRARY_ERROR = 25; public static final int PR_FIND_SYMBOL_ERROR = 26; public static final int PR_INSUFFICIENT_RESOURCES_ERROR = 27; public static final int PR_DIRECTORY_LOOKUP_ERROR = 28; public static final int PR_TPD_RANGE_ERROR = 29; public static final int PR_PROC_DESC_TABLE_FULL_ERROR = 30; public static final int PR_SYS_DESC_TABLE_FULL_ERROR = 31; public static final int PR_NOT_SOCKET_ERROR = 32; public static final int PR_NOT_TCP_SOCKET_ERROR = 33; public static final int PR_SOCKET_ADDRESS_IS_BOUND_ERROR = 34; public static final int PR_NO_ACCESS_RIGHTS_ERROR = 35; public static final int PR_OPERATION_NOT_SUPPORTED_ERROR = 36; public static final int PR_PROTOCOL_NOT_SUPPORTED_ERROR = 37; public static final int PR_REMOTE_FILE_ERROR = 38; public static final int PR_BUFFER_OVERFLOW_ERROR = 39; public static final int PR_CONNECT_RESET_ERROR = 40; public static final int PR_RANGE_ERROR = 41; public static final int PR_DEADLOCK_ERROR = 42; public static final int PR_FILE_IS_LOCKED_ERROR = 43; public static final int PR_FILE_TOO_BIG_ERROR = 44; public static final int PR_NO_DEVICE_SPACE_ERROR = 45; public static final int PR_PIPE_ERROR = 46; public static final int PR_NO_SEEK_DEVICE_ERROR = 47; public static final int PR_IS_DIRECTORY_ERROR = 48; public static final int PR_LOOP_ERROR = 49; public static final int PR_NAME_TOO_LONG_ERROR = 50; public static final int PR_FILE_NOT_FOUND_ERROR = 51; public static final int PR_NOT_DIRECTORY_ERROR = 52; public static final int PR_READ_ONLY_FILESYSTEM_ERROR = 53; public static final int PR_DIRECTORY_NOT_EMPTY_ERROR = 54; public static final int PR_FILESYSTEM_MOUNTED_ERROR = 55; public static final int PR_NOT_SAME_DEVICE_ERROR = 56; public static final int PR_DIRECTORY_CORRUPTED_ERROR = 57; public static final int PR_FILE_EXISTS_ERROR = 58; public static final int PR_MAX_DIRECTORY_ENTRIES_ERROR = 59; public static final int PR_INVALID_DEVICE_STATE_ERROR = 60; public static final int PR_DEVICE_IS_LOCKED_ERROR = 61; public static final int PR_NO_MORE_FILES_ERROR = 62; public static final int PR_END_OF_FILE_ERROR = 63; public static final int PR_FILE_SEEK_ERROR = 64; public static final int PR_FILE_IS_BUSY_ERROR = 65; public static final int PR_OPERATION_ABORTED_ERROR = 66; public static final int PR_IN_PROGRESS_ERROR = 67; public static final int PR_ALREADY_INITIATED_ERROR = 68; public static final int PR_GROUP_EMPTY_ERROR = 69; public static final int PR_INVALID_STATE_ERROR = 70; public static final int PR_NETWORK_DOWN_ERROR = 71; public static final int PR_SOCKET_SHUTDOWN_ERROR = 72; public static final int PR_CONNECT_ABORTED_ERROR = 73; public static final int PR_HOST_UNREACHABLE_ERROR = 74; public static final int SSL_ERROR_BASE = 77; public static final int SSL_ERROR_EXPORT_ONLY_SERVER = 78; public static final int SSL_ERROR_US_ONLY_SERVER = 79; public static final int SSL_ERROR_NO_CYPHER_OVERLAP = 80; public static final int SSL_ERROR_NO_CERTIFICATE = 81; public static final int SSL_ERROR_BAD_CERTIFICATE = 82; public static final int SSL_ERROR_BAD_CLIENT = 83; public static final int SSL_ERROR_BAD_SERVER = 84; public static final int SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE = 85; public static final int SSL_ERROR_UNSUPPORTED_VERSION = 86; public static final int SSL_ERROR_WRONG_CERTIFICATE = 87; public static final int SSL_ERROR_BAD_CERT_DOMAIN = 88; public static final int SSL_ERROR_POST_WARNING = 89; public static final int SSL_ERROR_SSL2_DISABLED = 90; public static final int SSL_ERROR_BAD_MAC_READ = 91; public static final int SSL_ERROR_BAD_MAC_ALERT = 92; public static final int SSL_ERROR_BAD_CERT_ALERT = 93; public static final int SSL_ERROR_REVOKED_CERT_ALERT = 94; public static final int SSL_ERROR_EXPIRED_CERT_ALERT = 95; public static final int SSL_ERROR_SSL_DISABLED = 96; /** * @deprecated As of NSS 3.11, FORTEZZA is no longer supported. * SSL_ERROR_FORTEZZA_PQG is a placeholder for backward * compatibility. */ @Deprecated public static final int SSL_ERROR_FORTEZZA_PQG = 97; public static final int SSL_ERROR_UNKNOWN_CIPHER_SUITE = 98; public static final int SSL_ERROR_NO_CIPHERS_SUPPORTED = 99; public static final int SSL_ERROR_BAD_BLOCK_PADDING = 100; public static final int SSL_ERROR_RX_RECORD_TOO_LONG = 101; public static final int SSL_ERROR_TX_RECORD_TOO_LONG = 102; public static final int SSL_ERROR_RX_MALFORMED_HELLO_REQUEST = 103; public static final int SSL_ERROR_RX_MALFORMED_CLIENT_HELLO = 104; public static final int SSL_ERROR_RX_MALFORMED_SERVER_HELLO = 105; public static final int SSL_ERROR_RX_MALFORMED_CERTIFICATE = 106; public static final int SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH = 107; public static final int SSL_ERROR_RX_MALFORMED_CERT_REQUEST = 108; public static final int SSL_ERROR_RX_MALFORMED_HELLO_DONE = 109; public static final int SSL_ERROR_RX_MALFORMED_CERT_VERIFY = 110; public static final int SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH = 111; public static final int SSL_ERROR_RX_MALFORMED_FINISHED = 112; public static final int SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER = 113; public static final int SSL_ERROR_RX_MALFORMED_ALERT = 114; public static final int SSL_ERROR_RX_MALFORMED_HANDSHAKE = 115; public static final int SSL_ERROR_RX_MALFORMED_APPLICATION_DATA = 116; public static final int SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST = 117; public static final int SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO = 118; public static final int SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO = 119; public static final int SSL_ERROR_RX_UNEXPECTED_CERTIFICATE = 120; public static final int SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH = 121; public static final int SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST = 122; public static final int SSL_ERROR_RX_UNEXPECTED_HELLO_DONE = 123; public static final int SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY = 124; public static final int SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH = 125; public static final int SSL_ERROR_RX_UNEXPECTED_FINISHED = 126; public static final int SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER = 127; public static final int SSL_ERROR_RX_UNEXPECTED_ALERT = 128; public static final int SSL_ERROR_RX_UNEXPECTED_HANDSHAKE = 129; public static final int SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA = 130; public static final int SSL_ERROR_RX_UNKNOWN_RECORD_TYPE = 131; public static final int SSL_ERROR_RX_UNKNOWN_HANDSHAKE = 132; public static final int SSL_ERROR_RX_UNKNOWN_ALERT = 133; public static final int SSL_ERROR_CLOSE_NOTIFY_ALERT = 134; public static final int SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT = 135; public static final int SSL_ERROR_DECOMPRESSION_FAILURE_ALERT = 136; public static final int SSL_ERROR_HANDSHAKE_FAILURE_ALERT = 137; public static final int SSL_ERROR_ILLEGAL_PARAMETER_ALERT = 138; public static final int SSL_ERROR_UNSUPPORTED_CERT_ALERT = 139; public static final int SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT = 140; public static final int SSL_ERROR_GENERATE_RANDOM_FAILURE = 141; public static final int SSL_ERROR_SIGN_HASHES_FAILURE = 142; public static final int SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE = 143; public static final int SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE = 144; public static final int SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE = 145; public static final int SSL_ERROR_ENCRYPTION_FAILURE = 146; public static final int SSL_ERROR_DECRYPTION_FAILURE = 147; public static final int SSL_ERROR_SOCKET_WRITE_FAILURE = 148; public static final int SSL_ERROR_MD5_DIGEST_FAILURE = 149; public static final int SSL_ERROR_SHA_DIGEST_FAILURE = 150; public static final int SSL_ERROR_MAC_COMPUTATION_FAILURE = 151; public static final int SSL_ERROR_SYM_KEY_CONTEXT_FAILURE = 152; public static final int SSL_ERROR_SYM_KEY_UNWRAP_FAILURE = 153; public static final int SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED = 154; public static final int SSL_ERROR_IV_PARAM_FAILURE = 155; public static final int SSL_ERROR_INIT_CIPHER_SUITE_FAILURE = 156; public static final int SSL_ERROR_SESSION_KEY_GEN_FAILURE = 157; public static final int SSL_ERROR_NO_SERVER_KEY_FOR_ALG = 158; public static final int SSL_ERROR_TOKEN_INSERTION_REMOVAL = 159; public static final int SSL_ERROR_TOKEN_SLOT_NOT_FOUND = 160; public static final int SSL_ERROR_NO_COMPRESSION_OVERLAP = 161; public static final int SSL_ERROR_HANDSHAKE_NOT_COMPLETED = 162; public static final int SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE = 163; public static final int SSL_ERROR_CERT_KEA_MISMATCH = 164; public static final int SSL_ERROR_NO_TRUSTED_SSL_CLIENT_CA = 165; public static final int SSL_ERROR_SESSION_NOT_FOUND = 166; public static final int SSL_ERROR_DECRYPTION_FAILED_ALERT = 167; public static final int SSL_ERROR_RECORD_OVERFLOW_ALERT = 168; public static final int SSL_ERROR_UNKNOWN_CA_ALERT = 169; public static final int SSL_ERROR_ACCESS_DENIED_ALERT = 170; public static final int SSL_ERROR_DECODE_ERROR_ALERT = 171; public static final int SSL_ERROR_DECRYPT_ERROR_ALERT = 172; public static final int SSL_ERROR_EXPORT_RESTRICTION_ALERT = 173; public static final int SSL_ERROR_PROTOCOL_VERSION_ALERT = 174; public static final int SSL_ERROR_INSUFFICIENT_SECURITY_ALERT = 175; public static final int SSL_ERROR_INTERNAL_ERROR_ALERT = 176; public static final int SSL_ERROR_USER_CANCELED_ALERT = 177; public static final int SSL_ERROR_NO_RENEGOTIATION_ALERT = 178; public static final int SEC_ERROR_IO = 179; public static final int SEC_ERROR_LIBRARY_FAILURE = 180; public static final int SEC_ERROR_BAD_DATA = 181; public static final int SEC_ERROR_OUTPUT_LEN = 182; public static final int SEC_ERROR_INPUT_LEN = 183; public static final int SEC_ERROR_INVALID_ARGS = 184; public static final int SEC_ERROR_INVALID_ALGORITHM = 185; public static final int SEC_ERROR_INVALID_AVA = 186; public static final int SEC_ERROR_INVALID_TIME = 187; public static final int SEC_ERROR_BAD_DER = 188; public static final int SEC_ERROR_BAD_SIGNATURE = 189; public static final int SEC_ERROR_EXPIRED_CERTIFICATE = 190; public static final int SEC_ERROR_REVOKED_CERTIFICATE = 191; public static final int SEC_ERROR_UNKNOWN_ISSUER = 192; public static final int SEC_ERROR_BAD_KEY = 193; public static final int SEC_ERROR_BAD_PASSWORD = 194; public static final int SEC_ERROR_RETRY_PASSWORD = 195; public static final int SEC_ERROR_NO_NODELOCK = 196; public static final int SEC_ERROR_BAD_DATABASE = 197; public static final int SEC_ERROR_NO_MEMORY = 198; public static final int SEC_ERROR_UNTRUSTED_ISSUER = 199; public static final int SEC_ERROR_UNTRUSTED_CERT = 200; public static final int SEC_ERROR_DUPLICATE_CERT = 201; public static final int SEC_ERROR_DUPLICATE_CERT_NAME = 202; public static final int SEC_ERROR_ADDING_CERT = 203; public static final int SEC_ERROR_FILING_KEY = 204; public static final int SEC_ERROR_NO_KEY = 205; public static final int SEC_ERROR_CERT_VALID = 206; public static final int SEC_ERROR_CERT_NOT_VALID = 207; public static final int SEC_ERROR_CERT_NO_RESPONSE = 208; public static final int SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE = 209; public static final int SEC_ERROR_CRL_EXPIRED = 210; public static final int SEC_ERROR_CRL_BAD_SIGNATURE = 211; public static final int SEC_ERROR_CRL_INVALID = 212; public static final int SEC_ERROR_EXTENSION_VALUE_INVALID = 213; public static final int SEC_ERROR_EXTENSION_NOT_FOUND = 214; public static final int SEC_ERROR_CA_CERT_INVALID = 215; public static final int SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID = 216; public static final int SEC_ERROR_CERT_USAGES_INVALID = 217; public static final int SEC_INTERNAL_ONLY = 218; public static final int SEC_ERROR_INVALID_KEY = 219; public static final int SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION = 220; public static final int SEC_ERROR_OLD_CRL = 221; public static final int SEC_ERROR_NO_EMAIL_CERT = 222; public static final int SEC_ERROR_NO_RECIPIENT_CERTS_QUERY = 223; public static final int SEC_ERROR_NOT_A_RECIPIENT = 224; public static final int SEC_ERROR_PKCS7_KEYALG_MISMATCH = 225; public static final int SEC_ERROR_PKCS7_BAD_SIGNATURE = 226; public static final int SEC_ERROR_UNSUPPORTED_KEYALG = 227; public static final int SEC_ERROR_DECRYPTION_DISALLOWED = 228; /** * @deprecated As of NSS 3.11, FORTEZZA is no longer supported. * XP_SEC_FORTEZZA_BAD_CARD, XP_SEC_FORTEZZA_NO_CARD, * XP_SEC_FORTEZZA_NONE_SELECTED, XP_SEC_FORTEZZA_MORE_INFO * XP_SEC_FORTEZZA_PERSON_NOT_FOUND, XP_SEC_FORTEZZA_NO_MORE_INFO * XP_SEC_FORTEZZA_BAD_PIN and XP_SEC_FORTEZZA_PERSON_ERROR are * placeholder for backward compatibility. */ @Deprecated public static final int XP_SEC_FORTEZZA_BAD_CARD = 229; @Deprecated public static final int XP_SEC_FORTEZZA_NO_CARD = 230; @Deprecated public static final int XP_SEC_FORTEZZA_NONE_SELECTED = 231; @Deprecated public static final int XP_SEC_FORTEZZA_MORE_INFO = 232; @Deprecated public static final int XP_SEC_FORTEZZA_PERSON_NOT_FOUND = 233; @Deprecated public static final int XP_SEC_FORTEZZA_NO_MORE_INFO = 234; @Deprecated public static final int XP_SEC_FORTEZZA_BAD_PIN = 235; @Deprecated public static final int XP_SEC_FORTEZZA_PERSON_ERROR = 236; public static final int SEC_ERROR_NO_KRL = 237; public static final int SEC_ERROR_KRL_EXPIRED = 238; public static final int SEC_ERROR_KRL_BAD_SIGNATURE = 239; public static final int SEC_ERROR_REVOKED_KEY = 240; public static final int SEC_ERROR_KRL_INVALID = 241; public static final int SEC_ERROR_NEED_RANDOM = 242; public static final int SEC_ERROR_NO_MODULE = 243; public static final int SEC_ERROR_NO_TOKEN = 244; public static final int SEC_ERROR_READ_ONLY = 245; public static final int SEC_ERROR_NO_SLOT_SELECTED = 246; public static final int SEC_ERROR_CERT_NICKNAME_COLLISION = 247; public static final int SEC_ERROR_KEY_NICKNAME_COLLISION = 248; public static final int SEC_ERROR_SAFE_NOT_CREATED = 249; public static final int SEC_ERROR_BAGGAGE_NOT_CREATED = 250; public static final int XP_JAVA_REMOVE_PRINCIPAL_ERROR = 251; public static final int XP_JAVA_DELETE_PRIVILEGE_ERROR = 252; public static final int XP_JAVA_CERT_NOT_EXISTS_ERROR = 253; public static final int SEC_ERROR_BAD_EXPORT_ALGORITHM = 254; public static final int SEC_ERROR_EXPORTING_CERTIFICATES = 255; public static final int SEC_ERROR_IMPORTING_CERTIFICATES = 256; public static final int SEC_ERROR_PKCS12_DECODING_PFX = 257; public static final int SEC_ERROR_PKCS12_INVALID_MAC = 258; public static final int SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM = 259; public static final int SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE = 260; public static final int SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE = 261; public static final int SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM = 262; public static final int SEC_ERROR_PKCS12_UNSUPPORTED_VERSION = 263; public static final int SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT = 264; public static final int SEC_ERROR_PKCS12_CERT_COLLISION = 265; public static final int SEC_ERROR_USER_CANCELLED = 266; public static final int SEC_ERROR_PKCS12_DUPLICATE_DATA = 267; public static final int SEC_ERROR_MESSAGE_SEND_ABORTED = 268; public static final int SEC_ERROR_INADEQUATE_KEY_USAGE = 269; public static final int SEC_ERROR_INADEQUATE_CERT_TYPE = 270; public static final int SEC_ERROR_CERT_ADDR_MISMATCH = 271; public static final int SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY = 272; public static final int SEC_ERROR_PKCS12_IMPORTING_CERT_CHAIN = 273; public static final int SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME = 274; public static final int SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY = 275; public static final int SEC_ERROR_PKCS12_UNABLE_TO_WRITE = 276; public static final int SEC_ERROR_PKCS12_UNABLE_TO_READ = 277; public static final int SEC_ERROR_PKCS12_KEY_DATABASE_NOT_INITIALIZED = 278; public static final int SEC_ERROR_KEYGEN_FAIL = 279; public static final int SEC_ERROR_INVALID_PASSWORD = 280; public static final int SEC_ERROR_RETRY_OLD_PASSWORD = 281; public static final int SEC_ERROR_BAD_NICKNAME = 282; /** * @deprecated As of NSS 3.11, FORTEZZA is no longer supported. * SEC_ERROR_NOT_FORTEZZA_ISSUER is a placeholder for backward * compatibility. */ @Deprecated public static final int SEC_ERROR_NOT_FORTEZZA_ISSUER = 283; public static final int SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY = 284; public static final int SEC_ERROR_JS_INVALID_MODULE_NAME = 285; public static final int SEC_ERROR_JS_INVALID_DLL = 286; public static final int SEC_ERROR_JS_ADD_MOD_FAILURE = 287; public static final int SEC_ERROR_JS_DEL_MOD_FAILURE = 288; public static final int SEC_ERROR_OLD_KRL = 289; public static final int SEC_ERROR_CKL_CONFLICT = 290; public static final int SEC_ERROR_CERT_NOT_IN_NAME_SPACE = 291; public static final int SEC_ERROR_KRL_NOT_YET_VALID = 292; public static final int SEC_ERROR_CRL_NOT_YET_VALID = 293; public static final int SEC_ERROR_UNKNOWN_CERT = 294; public static final int SEC_ERROR_UNKNOWN_SIGNER = 295; public static final int SEC_ERROR_CERT_BAD_ACCESS_LOCATION = 296; public static final int SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE = 297; public static final int SEC_ERROR_OCSP_BAD_HTTP_RESPONSE = 298; public static final int SEC_ERROR_OCSP_MALFORMED_REQUEST = 299; public static final int SEC_ERROR_OCSP_SERVER_ERROR = 300; public static final int SEC_ERROR_OCSP_TRY_SERVER_LATER = 301; public static final int SEC_ERROR_OCSP_REQUEST_NEEDS_SIG = 302; public static final int SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST = 303; public static final int SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS = 304; public static final int SEC_ERROR_OCSP_UNKNOWN_CERT = 305; public static final int SEC_ERROR_OCSP_NOT_ENABLED = 306; public static final int SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER = 307; public static final int SEC_ERROR_OCSP_MALFORMED_RESPONSE = 308; public static final int SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE = 309; public static final int SEC_ERROR_OCSP_FUTURE_RESPONSE = 310; public static final int SEC_ERROR_OCSP_OLD_RESPONSE = 311; public static final int SEC_ERROR_DIGEST_NOT_FOUND = 312; public static final int SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE = 313; } jss-5.0.0/src/main/java/org/mozilla/jss/util/NativeProxy.java000066400000000000000000000216361412550063600241260ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.util; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.atomic.AtomicInteger; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.netscape.security.util.Utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * NativeProxy, a superclass for Java classes that mirror C data structures. * * It contains some code to help make sure that native memory is getting * freed properly. * * @author nicolson * @version $Revision$ $Date$ */ public abstract class NativeProxy implements AutoCloseable { public static Logger logger = LoggerFactory.getLogger(NativeProxy.class); private static final boolean saveStacktraces = assertsEnabled() && CryptoManager.JSS_DEBUG; /** * Create a NativeProxy from a byte array representing a C pointer. * This is the primary way of creating a NativeProxy; it should be called * from the constructor of your subclass. * * @param pointer A byte array, created with JSS_ptrToByteArray, that * contains a pointer pointing to a native data structure. The * NativeProxy instance acts as a proxy for that native data structure. */ public NativeProxy(byte[] pointer) { this(pointer, true); } /** * Create a NativeProxy from a byte array representing a C pointer. * This allows for creating an untracked NativeProxy instance (when * track=false), which allows for creating NativeProxy instances out * of stack-allocated variables and/or creating NativeProxies which * aren't freed. */ protected NativeProxy(byte[] pointer, boolean track) { mPointer = pointer; mHashCode = registryIndex.getAndIncrement(); if (mPointer != null) { mHashCode += Arrays.hashCode(mPointer); } if (track && saveStacktraces) { assert (pointer != null); registry.add(this); mTrace = Arrays.toString(Thread.currentThread().getStackTrace()); } } /** * Deep comparison operator. * * @return true if obj has the same underlying native * pointer. false if the obj is null or has * a different underlying native pointer. */ @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (!(obj instanceof NativeProxy)) { return false; } NativeProxy nObj = (NativeProxy) obj; if (this.mPointer == null || nObj.mPointer == null) { return false; } return Arrays.equals(this.mPointer, nObj.mPointer); } /** * Hash code based around mPointer value. * * Note that Object.hashCode() isn't sufficient as it tries to determine * the Object's value based on all internal variables. Because we want a * single static hashCode that is unique to each instance of nativeProxy, * we construct it up front based on an incrementing counter and cache it * throughout the lifetime of this object. */ @Override public int hashCode() { return mHashCode; } /** * Release the native resources used by this proxy. * Subclasses of NativeProxy must define this method to clean up * data structures in C code that are referenced by this proxy. * releaseNativeResources() will usually be implemented as a native method. *

* You don't call this method; NativeProxy.finalize() or close() calls * it for you. *

* * If you free these resources explicitly, call clear(); instead. */ protected abstract void releaseNativeResources() throws Exception; /** * Finalize this NativeProxy by releasing its native resources. * The finalizer calls releaseNativeResources() so you don't have to. * This finalizer should be called from the finalize() method of all * subclasses: * class MyProxy extends NativeProxy { * [...] * protected void finalize() throws Throwable { * // do any object-specific finalization other than * // releasing native resources * [...] * super.finalize(); * } * } * * @deprecated finalize() in Object has been deprecated. Use close(...) * from the AutoCloseable interface instead. */ @Override @Deprecated protected void finalize() throws Throwable { close(); } /** * Close this NativeProxy by releasing its native resources if they * haven't otherwise been freed. * * See comment in finalize. */ @Override public final void close() throws Exception { try { if (mPointer != null) { releaseNativeResources(); } } finally { clear(); } } /** * Call clear(...) to clear the value of the pointer, setting it to null. * * This should be used when the pointer has been freed by another means. * Similar to finalize(...) or close(...), except that it doesn't call * releaseNativeResources(...). * * See also: JSS_clearPtrFromProxy(...) in jssutil.h */ public final void clear() { this.mPointer = null; // registry.remove(this); } /** * Whether or not this is a null pointer. */ public boolean isNull() { return this.mPointer == null; } /** * Byte array containing native pointer bytes. */ private byte mPointer[]; private int mHashCode; /** * String containing backtrace of pointer generation. */ private String mTrace; /** *

* Native Proxy Registry *

* In debug mode, we keep track of all NativeProxy objects in a * static registry. Whenever a NativeProxy is constructed, it * registers. Whenever it finalizes, it unregisters. At the end of * the game, we should be able to garbage collect and then assert that * the registry is empty. This could be done, for example, in the * jssjava JVM after main() completes. * * This registration process verifies that people are calling * NativeProxy.finalize() from their subclasses of NativeProxy, so that * releaseNativeResources() gets called. */ static Set registry = Collections.newSetFromMap(new WeakHashMap()); static AtomicInteger registryIndex = new AtomicInteger(); @Override public String toString() { if (mPointer == null) { return this.getClass().getName() + "[" + mHashCode + "@null]"; } return this.getClass().getName() + "[" + mHashCode + "@" + Utils.HexEncode(mPointer) + "]"; } /** * Internal helper to check whether or not assertions are enabled in the * JVM. * * See: https://docs.oracle.com/javase/8/docs/technotes/guides/language/assert.html */ private static boolean assertsEnabled() { boolean enabled = false; assert enabled = true; return enabled; } /** * Assert that the Registry is empty. Only works in debug mode; in * ship mode, it is a no-op. If the Registry is not empty when this * is called, an assertion (org.mozilla.jss.util.AssertionException) * is thrown. */ public synchronized static void assertRegistryEmpty() { if (!registry.isEmpty()) { logger.warn(registry.size() + " NativeProxys are still registered."); if (saveStacktraces) { for (NativeProxy proxy : registry) { logger.warn("\t" + Arrays.toString(proxy.mPointer) + " ::: " + proxy.mTrace); } } } else { logger.debug("NativeProxy registry is empty"); } } /** * Unsafe: Purges all NativeProxies from memory. * * In the rare instances where we wish to shutdown an existing * CryptoManager, all native proxies need to be cleared and freed. * This will result in any lingering references to stop working, but * should ensure that an application can recover from this scenario. */ public synchronized static void purgeAllInRegistry() throws Exception { Exception first = null; HashSet registryClone = new HashSet(registry.size()); registryClone.addAll(registry); for (NativeProxy proxy : registryClone) { try { proxy.close(); } catch (Exception e) { if (first == null) { first = e; } } } if (first != null) { throw first; } } } jss-5.0.0/src/main/java/org/mozilla/jss/util/NotImplementedException.java000066400000000000000000000014671412550063600264410ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.util; /** * This exception is thrown whenever something isn't implemented. */ public class NotImplementedException extends Exception { private static final long serialVersionUID = 1L; public NotImplementedException() { super(); } public NotImplementedException(String mesg) { super(mesg); } public NotImplementedException(String mesg, Throwable cause) { super(mesg, cause); } public NotImplementedException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(mesg, cause, enableSuppression, writableStackTrace); } } jss-5.0.0/src/main/java/org/mozilla/jss/util/NullPasswordCallback.java000066400000000000000000000017541412550063600257070ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.util; /** * A PasswordCallback that immediately gives up. This should be used * when a user is not available to enter a password. Any operations * that require a password will fail if this is used, unless the token * has already been logged in manually. * * @see org.mozilla.jss.crypto.CryptoToken#login */ public class NullPasswordCallback implements PasswordCallback { @Override public Password getPasswordFirstAttempt(PasswordCallbackInfo info) throws PasswordCallback.GiveUpException { throw new PasswordCallback.GiveUpException(); } @Override public Password getPasswordAgain(PasswordCallbackInfo info) throws PasswordCallback.GiveUpException { throw new PasswordCallback.GiveUpException(); } } jss-5.0.0/src/main/java/org/mozilla/jss/util/Password.java000066400000000000000000000227111412550063600234330ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.util; import java.io.CharConversionException; import java.io.Console; import java.io.PrintWriter; import java.io.StringWriter; import java.util.Arrays; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Stores a password. clear should be * called when the password is no longer needed so that the sensitive * information is not left in memory. *

* A Password can be used as a hard-coded * PasswordCallback. * * @see PasswordCallback */ public class Password implements PasswordCallback, Cloneable, java.io.Serializable { private static final long serialVersionUID = 1L; public static Logger logger = LoggerFactory.getLogger(Password.class); // store the location where the Password object was created private StackTraceElement[] stackTrace = new Throwable().getStackTrace(); /** * Don't use this if you aren't Password. */ private Password() { cleared = true; } /** * Creates a Password from a char array, then wipes the char array. * * @param pw A char[] containing the password. This array will be * cleared (set to zeroes) by the constructor. */ public Password(char[] pw) { int i; int length = pw.length; cleared = false; password = new char[length]; for (i = 0; i < length; i++) { password[i] = pw[i]; pw[i] = 0; } } /** * An implementation of * PasswordCallback.getPasswordFirstAttempt. This allows * a Password object to be treated as a * PasswordCallback. This method simply returns a clone * of the password. * * @return A copy of the password. The caller is responsible for * clearing this copy. */ @Override public synchronized Password getPasswordFirstAttempt(PasswordCallbackInfo info) throws PasswordCallback.GiveUpException { if (cleared) { throw new PasswordCallback.GiveUpException(); } return (Password) this.clone(); } /** * Compares this password to another and returns true if they * are the same. */ @Override public synchronized boolean equals(Object obj) { if (!(obj instanceof Password)) { return false; } Password pw = (Password) obj; if (pw.password == null || password == null) { return false; } if (pw.password.length != password.length) { return false; } for (int i = 0; i < password.length; i++) { if (pw.password[i] != password[i]) { return false; } } return true; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + Arrays.hashCode(password); return result; } /** * An implementation of PasswordCallback.getPasswordAgain. * This allows a Password object to be used as a * PasswordCallback. This method is only called after * a call to getPasswordFirstAttempt returned the wrong * password. This means the password is incorrect and there's no * sense returning it again, so a GiveUpException is thrown. */ @Override public synchronized Password getPasswordAgain(PasswordCallbackInfo info) throws PasswordCallback.GiveUpException { throw new PasswordCallback.GiveUpException(); } /** * Returns the char array underlying this password. It must not be * modified in any way. */ public synchronized char[] getChars() { return password; } /** * Returns a char array that is a copy of the password. * The caller is responsible for wiping the returned array, * for example using wipeChars. */ public synchronized char[] getCharCopy() { return password.clone(); } /** * Returns a null-terminated byte array that is the byte-encoding of * this password. * The returned array is a copy of the password. * The caller is responsible for wiping the returned array, * for example using wipeChars. */ synchronized byte[] getByteCopy() { return charToByte(password.clone()); } /** * Clears the password so that sensitive data is no longer present * in memory. This should be called as soon as the password is no * longer needed. */ public synchronized void clear() { int i; int len = password.length; for (i = 0; i < len; i++) { password[i] = 0; } cleared = true; } /** * Clones the password. The resulting clone will be completely independent * of the parent, which means it will have to be separately cleared. */ @Override public synchronized Object clone() { Password dolly = new Password(); dolly.password = password.clone(); dolly.cleared = cleared; return dolly; } /** * The finalizer clears the sensitive information before releasing * it to the garbage collector, but it should have been cleared manually * before this point anyway. * * @deprecated finalize() in Object has been deprecated */ @Override @Deprecated protected void finalize() throws Throwable { if (cleared) return; // clear the password first clear(); StringWriter sw = new StringWriter(); PrintWriter out = new PrintWriter(sw, true); int i = 0; // show where the password was created for (; i < stackTrace.length; i++) { StackTraceElement ste = stackTrace[i]; String className = ste.getClassName(); if (Password.class.getName().equals(className)) continue; out.println("Uncleared Password object created at " + ste); i++; break; } // show who called the code for (; i < stackTrace.length; i++) { StackTraceElement ste = stackTrace[i]; out.println(" called by " + ste); } out.println("Please report the above trace to your software vendors."); logger.warn(sw.toString()); } /** * Converts a char array to a null-terminated byte array using a standard * encoding, which is currently UTF8. The caller is responsible for * clearing the copy (with wipeBytes, for example). * * @param charArray A character array, which should not be null. It will * be wiped with zeroes. * @return A copy of the charArray, converted from Unicode to UTF8. It * is the responsibility of the caller to clear the output byte array; * wipeBytes is ideal for this purpose. * @see Password#wipeBytes */ public static byte[] charToByte(char[] charArray) { byte[] byteArray; assert (charArray != null); try { byteArray = UTF8Converter.UnicodeToUTF8NullTerm(charArray); } catch (CharConversionException e) { throw new RuntimeException("Password could not be converted from" + " Unicode: " + e.getMessage(), e); // byteArray = new byte[] {0}; } finally { wipeChars(charArray); } return byteArray; } /** * Wipes a byte array by setting all its elements to zero. * null must not be passed in. */ public static void wipeBytes(byte[] byteArray) { assert (byteArray != null); UTF8Converter.wipeBytes(byteArray); } /** * Wipes a char array by setting all its elements to zero. * null must not be passed in. */ public static void wipeChars(char[] charArray) { int i; assert (charArray != null); for (i = 0; i < charArray.length; i++) { charArray[i] = 0; } } /** * Reads a password from the console with echo disabled. This is a blocking * call which will return after the user types a newline. * It only works with ASCII password characters. * The call is synchronized because it alters terminal settings in * a way that is not thread-safe. * * @exception org.mozilla.jss.util.PasswordCallback.GiveUpException * If the user enters no password (just hits * <enter>). * @return The password the user entered at the command line. */ public static Password readPasswordFromConsole() throws PasswordCallback.GiveUpException { Console console = System.console(); char[] password = console.readPassword(); if (password == null || password.length == 0) { throw new PasswordCallback.GiveUpException(); } return new Password(password); } // The password, stored as a char[] so we can clear it. Passwords // should never be stored in Strings because Strings can't be cleared. private char[] password; // true if the char[] has been cleared of sensitive information private boolean cleared; } jss-5.0.0/src/main/java/org/mozilla/jss/util/PasswordCallback.java000066400000000000000000000044141412550063600250500ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.util; /** * Represents a password callback, which is called to login to the key * database and to PKCS #11 tokens. *

The simplest implementation of a PasswordCallback is a Password object. * * @see org.mozilla.jss.util.Password * @see org.mozilla.jss.util.NullPasswordCallback * @see org.mozilla.jss.util.ConsolePasswordCallback * @see org.mozilla.jss.CryptoManager#setPasswordCallback */ public interface PasswordCallback { /** * This exception is thrown if the PasswordCallback * wants to stop guessing passwords. */ public static class GiveUpException extends Exception { private static final long serialVersionUID = 1L; public GiveUpException() { super(); } public GiveUpException(String mesg) { super(mesg); } } /** * Supplies a password. This is called on the first attempt; if it * returns the wrong password, getPasswordAgain will * be called on subsequent attempts. * * @param info Information about the token that is being logged into. * @return The password. This password object is owned by and will * be cleared by the caller. * @exception GiveUpException If the callback does not want to supply * a password. */ public Password getPasswordFirstAttempt(PasswordCallbackInfo info) throws GiveUpException; /** * Tries supplying a password again. This callback will be called if * the first callback returned an invalid password. It will be called * repeatedly until it returns a correct password, or it gives up by * throwing a GiveUpException. * * @param info Information about the token that is being logged into. * @return The password. This password object is owned by and will * be cleared by the caller. * @exception GiveUpException If the callback does not want to supply * a password. This may often be the case if the first attempt failed. */ public Password getPasswordAgain(PasswordCallbackInfo info) throws GiveUpException; } jss-5.0.0/src/main/java/org/mozilla/jss/util/PasswordCallbackInfo.java000066400000000000000000000023471412550063600256670ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.util; /** * An object of this class is passed to a PasswordCallback to give it * information about the token that is being logged into. */ public class PasswordCallbackInfo { /** * @param name The name of the file or token that is being logged into. * @param type The type of object (FILE or * TOKEN) that is being logged into. */ public PasswordCallbackInfo(String name, int type) { assert(type==FILE || type==TOKEN); this.name = name; this.type = type; } /** * The name of the file or token that is being logged into. */ public String getName() { return name; } /** * The type of object that is being logged into, FILE * or TOKEN. */ public int getType() { return type; } protected String name; protected int type; /** * Logging into a file. */ static public final int FILE = 0; /** * Logging into a PKCS #11 token. */ static public final int TOKEN = 1; } jss-5.0.0/src/main/java/org/mozilla/jss/util/SECerrs.h000066400000000000000000000470521412550063600224520ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* General security error codes */ /* Caller must #include "secerr.h" */ ER3(SEC_ERROR_IO, SEC_ERROR_BASE + 0, "An I/O error occurred during security authorization.") ER3(SEC_ERROR_LIBRARY_FAILURE, SEC_ERROR_BASE + 1, "security library failure.") ER3(SEC_ERROR_BAD_DATA, SEC_ERROR_BASE + 2, "security library: received bad data.") ER3(SEC_ERROR_OUTPUT_LEN, SEC_ERROR_BASE + 3, "security library: output length error.") ER3(SEC_ERROR_INPUT_LEN, SEC_ERROR_BASE + 4, "security library has experienced an input length error.") ER3(SEC_ERROR_INVALID_ARGS, SEC_ERROR_BASE + 5, "security library: invalid arguments.") ER3(SEC_ERROR_INVALID_ALGORITHM, SEC_ERROR_BASE + 6, "security library: invalid algorithm.") ER3(SEC_ERROR_INVALID_AVA, SEC_ERROR_BASE + 7, "security library: invalid AVA.") ER3(SEC_ERROR_INVALID_TIME, SEC_ERROR_BASE + 8, "Improperly formatted time string.") ER3(SEC_ERROR_BAD_DER, SEC_ERROR_BASE + 9, "security library: improperly formatted DER-encoded message.") ER3(SEC_ERROR_BAD_SIGNATURE, SEC_ERROR_BASE + 10, "Peer's certificate has an invalid signature.") ER3(SEC_ERROR_EXPIRED_CERTIFICATE, SEC_ERROR_BASE + 11, "Peer's Certificate has expired.") ER3(SEC_ERROR_REVOKED_CERTIFICATE, SEC_ERROR_BASE + 12, "Peer's Certificate has been revoked.") ER3(SEC_ERROR_UNKNOWN_ISSUER, SEC_ERROR_BASE + 13, "Peer's Certificate issuer is not recognized.") ER3(SEC_ERROR_BAD_KEY, SEC_ERROR_BASE + 14, "Peer's public key is invalid.") ER3(SEC_ERROR_BAD_PASSWORD, SEC_ERROR_BASE + 15, "The security password entered is incorrect.") ER3(SEC_ERROR_RETRY_PASSWORD, SEC_ERROR_BASE + 16, "New password entered incorrectly. Please try again.") ER3(SEC_ERROR_NO_NODELOCK, SEC_ERROR_BASE + 17, "security library: no nodelock.") ER3(SEC_ERROR_BAD_DATABASE, SEC_ERROR_BASE + 18, "security library: bad database.") ER3(SEC_ERROR_NO_MEMORY, SEC_ERROR_BASE + 19, "security library: memory allocation failure.") ER3(SEC_ERROR_UNTRUSTED_ISSUER, SEC_ERROR_BASE + 20, "Peer's certificate issuer has been marked as not trusted by the user.") ER3(SEC_ERROR_UNTRUSTED_CERT, SEC_ERROR_BASE + 21, "Peer's certificate has been marked as not trusted by the user.") ER3(SEC_ERROR_DUPLICATE_CERT, (SEC_ERROR_BASE + 22), "Certificate already exists in your database.") ER3(SEC_ERROR_DUPLICATE_CERT_NAME, (SEC_ERROR_BASE + 23), "Downloaded certificate's name duplicates one already in your database.") ER3(SEC_ERROR_ADDING_CERT, (SEC_ERROR_BASE + 24), "Error adding certificate to database.") ER3(SEC_ERROR_FILING_KEY, (SEC_ERROR_BASE + 25), "Error refiling the key for this certificate.") ER3(SEC_ERROR_NO_KEY, (SEC_ERROR_BASE + 26), "The private key for this certificate cannot be found in key database") ER3(SEC_ERROR_CERT_VALID, (SEC_ERROR_BASE + 27), "This certificate is valid.") ER3(SEC_ERROR_CERT_NOT_VALID, (SEC_ERROR_BASE + 28), "This certificate is not valid.") ER3(SEC_ERROR_CERT_NO_RESPONSE, (SEC_ERROR_BASE + 29), "Cert Library: No Response") ER3(SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE, (SEC_ERROR_BASE + 30), "The certificate issuer's certificate has expired. Check your system date and time.") ER3(SEC_ERROR_CRL_EXPIRED, (SEC_ERROR_BASE + 31), "The CRL for the certificate's issuer has expired. Update it or check your system date and time.") ER3(SEC_ERROR_CRL_BAD_SIGNATURE, (SEC_ERROR_BASE + 32), "The CRL for the certificate's issuer has an invalid signature.") ER3(SEC_ERROR_CRL_INVALID, (SEC_ERROR_BASE + 33), "New CRL has an invalid format.") ER3(SEC_ERROR_EXTENSION_VALUE_INVALID, (SEC_ERROR_BASE + 34), "Certificate extension value is invalid.") ER3(SEC_ERROR_EXTENSION_NOT_FOUND, (SEC_ERROR_BASE + 35), "Certificate extension not found.") ER3(SEC_ERROR_CA_CERT_INVALID, (SEC_ERROR_BASE + 36), "Issuer certificate is invalid.") ER3(SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID, (SEC_ERROR_BASE + 37), "Certificate path length constraint is invalid.") ER3(SEC_ERROR_CERT_USAGES_INVALID, (SEC_ERROR_BASE + 38), "Certificate usages field is invalid.") ER3(SEC_INTERNAL_ONLY, (SEC_ERROR_BASE + 39), "**Internal ONLY module**") ER3(SEC_ERROR_INVALID_KEY, (SEC_ERROR_BASE + 40), "The key does not support the requested operation.") ER3(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION, (SEC_ERROR_BASE + 41), "Certificate contains unknown critical extension.") ER3(SEC_ERROR_OLD_CRL, (SEC_ERROR_BASE + 42), "New CRL is not later than the current one.") ER3(SEC_ERROR_NO_EMAIL_CERT, (SEC_ERROR_BASE + 43), "Not encrypted or signed: you do not yet have an email certificate.") ER3(SEC_ERROR_NO_RECIPIENT_CERTS_QUERY, (SEC_ERROR_BASE + 44), "Not encrypted: you do not have certificates for each of the recipients.") ER3(SEC_ERROR_NOT_A_RECIPIENT, (SEC_ERROR_BASE + 45), "Cannot decrypt: you are not a recipient, or matching certificate and \ private key not found.") ER3(SEC_ERROR_PKCS7_KEYALG_MISMATCH, (SEC_ERROR_BASE + 46), "Cannot decrypt: key encryption algorithm does not match your certificate.") ER3(SEC_ERROR_PKCS7_BAD_SIGNATURE, (SEC_ERROR_BASE + 47), "Signature verification failed: no signer found, too many signers found, \ or improper or corrupted data.") ER3(SEC_ERROR_UNSUPPORTED_KEYALG, (SEC_ERROR_BASE + 48), "Unsupported or unknown key algorithm.") ER3(SEC_ERROR_DECRYPTION_DISALLOWED, (SEC_ERROR_BASE + 49), "Cannot decrypt: encrypted using a disallowed algorithm or key size.") /* Fortezza Alerts */ ER3(XP_SEC_FORTEZZA_BAD_CARD, (SEC_ERROR_BASE + 50), "Fortezza card has not been properly initialized. \ Please remove it and return it to your issuer.") ER3(XP_SEC_FORTEZZA_NO_CARD, (SEC_ERROR_BASE + 51), "No Fortezza cards Found") ER3(XP_SEC_FORTEZZA_NONE_SELECTED, (SEC_ERROR_BASE + 52), "No Fortezza card selected") ER3(XP_SEC_FORTEZZA_MORE_INFO, (SEC_ERROR_BASE + 53), "Please select a personality to get more info on") ER3(XP_SEC_FORTEZZA_PERSON_NOT_FOUND, (SEC_ERROR_BASE + 54), "Personality not found") ER3(XP_SEC_FORTEZZA_NO_MORE_INFO, (SEC_ERROR_BASE + 55), "No more information on that Personality") ER3(XP_SEC_FORTEZZA_BAD_PIN, (SEC_ERROR_BASE + 56), "Invalid Pin") ER3(XP_SEC_FORTEZZA_PERSON_ERROR, (SEC_ERROR_BASE + 57), "Couldn't initialize Fortezza personalities.") /* end fortezza alerts. */ ER3(SEC_ERROR_NO_KRL, (SEC_ERROR_BASE + 58), "No KRL for this site's certificate has been found.") ER3(SEC_ERROR_KRL_EXPIRED, (SEC_ERROR_BASE + 59), "The KRL for this site's certificate has expired.") ER3(SEC_ERROR_KRL_BAD_SIGNATURE, (SEC_ERROR_BASE + 60), "The KRL for this site's certificate has an invalid signature.") ER3(SEC_ERROR_REVOKED_KEY, (SEC_ERROR_BASE + 61), "The key for this site's certificate has been revoked.") ER3(SEC_ERROR_KRL_INVALID, (SEC_ERROR_BASE + 62), "New KRL has an invalid format.") ER3(SEC_ERROR_NEED_RANDOM, (SEC_ERROR_BASE + 63), "security library: need random data.") ER3(SEC_ERROR_NO_MODULE, (SEC_ERROR_BASE + 64), "security library: no security module can perform the requested operation.") ER3(SEC_ERROR_NO_TOKEN, (SEC_ERROR_BASE + 65), "The security card or token does not exist, needs to be initialized, or has been removed.") ER3(SEC_ERROR_READ_ONLY, (SEC_ERROR_BASE + 66), "security library: read-only database.") ER3(SEC_ERROR_NO_SLOT_SELECTED, (SEC_ERROR_BASE + 67), "No slot or token was selected.") ER3(SEC_ERROR_CERT_NICKNAME_COLLISION, (SEC_ERROR_BASE + 68), "A certificate with the same nickname already exists.") ER3(SEC_ERROR_KEY_NICKNAME_COLLISION, (SEC_ERROR_BASE + 69), "A key with the same nickname already exists.") ER3(SEC_ERROR_SAFE_NOT_CREATED, (SEC_ERROR_BASE + 70), "error while creating safe object") ER3(SEC_ERROR_BAGGAGE_NOT_CREATED, (SEC_ERROR_BASE + 71), "error while creating baggage object") ER3(XP_JAVA_REMOVE_PRINCIPAL_ERROR, (SEC_ERROR_BASE + 72), "Couldn't remove the principal") ER3(XP_JAVA_DELETE_PRIVILEGE_ERROR, (SEC_ERROR_BASE + 73), "Couldn't delete the privilege") ER3(XP_JAVA_CERT_NOT_EXISTS_ERROR, (SEC_ERROR_BASE + 74), "This principal doesn't have a certificate") ER3(SEC_ERROR_BAD_EXPORT_ALGORITHM, (SEC_ERROR_BASE + 75), "Required algorithm is not allowed.") ER3(SEC_ERROR_EXPORTING_CERTIFICATES, (SEC_ERROR_BASE + 76), "Error attempting to export certificates.") ER3(SEC_ERROR_IMPORTING_CERTIFICATES, (SEC_ERROR_BASE + 77), "Error attempting to import certificates.") ER3(SEC_ERROR_PKCS12_DECODING_PFX, (SEC_ERROR_BASE + 78), "Unable to import. Decoding error. File not valid.") ER3(SEC_ERROR_PKCS12_INVALID_MAC, (SEC_ERROR_BASE + 79), "Unable to import. Invalid MAC. Incorrect password or corrupt file.") ER3(SEC_ERROR_PKCS12_UNSUPPORTED_MAC_ALGORITHM, (SEC_ERROR_BASE + 80), "Unable to import. MAC algorithm not supported.") ER3(SEC_ERROR_PKCS12_UNSUPPORTED_TRANSPORT_MODE,(SEC_ERROR_BASE + 81), "Unable to import. Only password integrity and privacy modes supported.") ER3(SEC_ERROR_PKCS12_CORRUPT_PFX_STRUCTURE, (SEC_ERROR_BASE + 82), "Unable to import. File structure is corrupt.") ER3(SEC_ERROR_PKCS12_UNSUPPORTED_PBE_ALGORITHM, (SEC_ERROR_BASE + 83), "Unable to import. Encryption algorithm not supported.") ER3(SEC_ERROR_PKCS12_UNSUPPORTED_VERSION, (SEC_ERROR_BASE + 84), "Unable to import. File version not supported.") ER3(SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT,(SEC_ERROR_BASE + 85), "Unable to import. Incorrect privacy password.") ER3(SEC_ERROR_PKCS12_CERT_COLLISION, (SEC_ERROR_BASE + 86), "Unable to import. Same nickname already exists in database.") ER3(SEC_ERROR_USER_CANCELLED, (SEC_ERROR_BASE + 87), "The user pressed cancel.") ER3(SEC_ERROR_PKCS12_DUPLICATE_DATA, (SEC_ERROR_BASE + 88), "Not imported, already in database.") ER3(SEC_ERROR_MESSAGE_SEND_ABORTED, (SEC_ERROR_BASE + 89), "Message not sent.") ER3(SEC_ERROR_INADEQUATE_KEY_USAGE, (SEC_ERROR_BASE + 90), "Certificate key usage inadequate for attempted operation.") ER3(SEC_ERROR_INADEQUATE_CERT_TYPE, (SEC_ERROR_BASE + 91), "Certificate type not approved for application.") ER3(SEC_ERROR_CERT_ADDR_MISMATCH, (SEC_ERROR_BASE + 92), "Address in signing certificate does not match address in message headers.") ER3(SEC_ERROR_PKCS12_UNABLE_TO_IMPORT_KEY, (SEC_ERROR_BASE + 93), "Unable to import. Error attempting to import private key.") ER3(SEC_ERROR_PKCS12_IMPORTING_CERT_CHAIN, (SEC_ERROR_BASE + 94), "Unable to import. Error attempting to import certificate chain.") ER3(SEC_ERROR_PKCS12_UNABLE_TO_LOCATE_OBJECT_BY_NAME, (SEC_ERROR_BASE + 95), "Unable to export. Unable to locate certificate or key by nickname.") ER3(SEC_ERROR_PKCS12_UNABLE_TO_EXPORT_KEY, (SEC_ERROR_BASE + 96), "Unable to export. Private Key could not be located and exported.") ER3(SEC_ERROR_PKCS12_UNABLE_TO_WRITE, (SEC_ERROR_BASE + 97), "Unable to export. Unable to write the export file.") ER3(SEC_ERROR_PKCS12_UNABLE_TO_READ, (SEC_ERROR_BASE + 98), "Unable to import. Unable to read the import file.") ER3(SEC_ERROR_PKCS12_KEY_DATABASE_NOT_INITIALIZED, (SEC_ERROR_BASE + 99), "Unable to export. Key database corrupt or deleted.") ER3(SEC_ERROR_KEYGEN_FAIL, (SEC_ERROR_BASE + 100), "Unable to generate public/private key pair.") ER3(SEC_ERROR_INVALID_PASSWORD, (SEC_ERROR_BASE + 101), "Password entered is invalid. Please pick a different one.") ER3(SEC_ERROR_RETRY_OLD_PASSWORD, (SEC_ERROR_BASE + 102), "Old password entered incorrectly. Please try again.") ER3(SEC_ERROR_BAD_NICKNAME, (SEC_ERROR_BASE + 103), "Certificate nickname already in use.") ER3(SEC_ERROR_NOT_FORTEZZA_ISSUER, (SEC_ERROR_BASE + 104), "Peer FORTEZZA chain has a non-FORTEZZA Certificate.") ER3(SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY, (SEC_ERROR_BASE + 105), "A sensitive key cannot be moved to the slot where it is needed.") ER3(SEC_ERROR_JS_INVALID_MODULE_NAME, (SEC_ERROR_BASE + 106), "Invalid module name.") ER3(SEC_ERROR_JS_INVALID_DLL, (SEC_ERROR_BASE + 107), "Invalid module path/filename") ER3(SEC_ERROR_JS_ADD_MOD_FAILURE, (SEC_ERROR_BASE + 108), "Unable to add module") ER3(SEC_ERROR_JS_DEL_MOD_FAILURE, (SEC_ERROR_BASE + 109), "Unable to delete module") ER3(SEC_ERROR_OLD_KRL, (SEC_ERROR_BASE + 110), "New KRL is not later than the current one.") ER3(SEC_ERROR_CKL_CONFLICT, (SEC_ERROR_BASE + 111), "New CKL has different issuer than current CKL. Delete current CKL.") ER3(SEC_ERROR_CERT_NOT_IN_NAME_SPACE, (SEC_ERROR_BASE + 112), "The Certifying Authority for this certificate is not permitted to issue a \ certificate with this name.") ER3(SEC_ERROR_KRL_NOT_YET_VALID, (SEC_ERROR_BASE + 113), "The key revocation list for this certificate is not yet valid.") ER3(SEC_ERROR_CRL_NOT_YET_VALID, (SEC_ERROR_BASE + 114), "The certificate revocation list for this certificate is not yet valid.") ER3(SEC_ERROR_UNKNOWN_CERT, (SEC_ERROR_BASE + 115), "The requested certificate could not be found.") ER3(SEC_ERROR_UNKNOWN_SIGNER, (SEC_ERROR_BASE + 116), "The signer's certificate could not be found.") ER3(SEC_ERROR_CERT_BAD_ACCESS_LOCATION, (SEC_ERROR_BASE + 117), "The location for the certificate status server has invalid format.") ER3(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_TYPE, (SEC_ERROR_BASE + 118), "The OCSP response cannot be fully decoded; it is of an unknown type.") ER3(SEC_ERROR_OCSP_BAD_HTTP_RESPONSE, (SEC_ERROR_BASE + 119), "The OCSP server returned unexpected/invalid HTTP data.") ER3(SEC_ERROR_OCSP_MALFORMED_REQUEST, (SEC_ERROR_BASE + 120), "The OCSP server found the request to be corrupted or improperly formed.") ER3(SEC_ERROR_OCSP_SERVER_ERROR, (SEC_ERROR_BASE + 121), "The OCSP server experienced an internal error.") ER3(SEC_ERROR_OCSP_TRY_SERVER_LATER, (SEC_ERROR_BASE + 122), "The OCSP server suggests trying again later.") ER3(SEC_ERROR_OCSP_REQUEST_NEEDS_SIG, (SEC_ERROR_BASE + 123), "The OCSP server requires a signature on this request.") ER3(SEC_ERROR_OCSP_UNAUTHORIZED_REQUEST, (SEC_ERROR_BASE + 124), "The OCSP server has refused this request as unauthorized.") ER3(SEC_ERROR_OCSP_UNKNOWN_RESPONSE_STATUS, (SEC_ERROR_BASE + 125), "The OCSP server returned an unrecognizable status.") ER3(SEC_ERROR_OCSP_UNKNOWN_CERT, (SEC_ERROR_BASE + 126), "The OCSP server has no status for the certificate.") ER3(SEC_ERROR_OCSP_NOT_ENABLED, (SEC_ERROR_BASE + 127), "You must enable OCSP before performing this operation.") ER3(SEC_ERROR_OCSP_NO_DEFAULT_RESPONDER, (SEC_ERROR_BASE + 128), "You must set the OCSP default responder before performing this operation.") ER3(SEC_ERROR_OCSP_MALFORMED_RESPONSE, (SEC_ERROR_BASE + 129), "The response from the OCSP server was corrupted or improperly formed.") ER3(SEC_ERROR_OCSP_UNAUTHORIZED_RESPONSE, (SEC_ERROR_BASE + 130), "The signer of the OCSP response is not authorized to give status for \ this certificate.") ER3(SEC_ERROR_OCSP_FUTURE_RESPONSE, (SEC_ERROR_BASE + 131), "The OCSP response is not yet valid (contains a date in the future).") ER3(SEC_ERROR_OCSP_OLD_RESPONSE, (SEC_ERROR_BASE + 132), "The OCSP response contains out-of-date information.") ER3(SEC_ERROR_DIGEST_NOT_FOUND, (SEC_ERROR_BASE + 133), "The CMS or PKCS #7 Digest was not found in signed message.") ER3(SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE, (SEC_ERROR_BASE + 134), "The CMS or PKCS #7 Message type is unsupported.") ER3(SEC_ERROR_MODULE_STUCK, (SEC_ERROR_BASE + 135), "PKCS #11 module could not be removed because it is still in use.") ER3(SEC_ERROR_BAD_TEMPLATE, (SEC_ERROR_BASE + 136), "Could not decode ASN.1 data. Specified template was invalid.") ER3(SEC_ERROR_CRL_NOT_FOUND, (SEC_ERROR_BASE + 137), "No matching CRL was found.") ER3(SEC_ERROR_REUSED_ISSUER_AND_SERIAL, (SEC_ERROR_BASE + 138), "You are attempting to import a cert with the same issuer/serial as \ an existing cert, but that is not the same cert.") ER3(SEC_ERROR_BUSY, (SEC_ERROR_BASE + 139), "NSS could not shutdown. Objects are still in use.") ER3(SEC_ERROR_EXTRA_INPUT, (SEC_ERROR_BASE + 140), "DER-encoded message contained extra unused data.") ER3(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE, (SEC_ERROR_BASE + 141), "Unsupported elliptic curve.") ER3(SEC_ERROR_UNSUPPORTED_EC_POINT_FORM, (SEC_ERROR_BASE + 142), "Unsupported elliptic curve point form.") ER3(SEC_ERROR_UNRECOGNIZED_OID, (SEC_ERROR_BASE + 143), "Unrecognized Object Identifier.") ER3(SEC_ERROR_OCSP_INVALID_SIGNING_CERT, (SEC_ERROR_BASE + 144), "Invalid OCSP signing certificate in OCSP response.") ER3(SEC_ERROR_REVOKED_CERTIFICATE_CRL, (SEC_ERROR_BASE + 145), "Certificate is revoked in issuer's certificate revocation list.") ER3(SEC_ERROR_REVOKED_CERTIFICATE_OCSP, (SEC_ERROR_BASE + 146), "Issuer's OCSP responder reports certificate is revoked.") ER3(SEC_ERROR_CRL_INVALID_VERSION, (SEC_ERROR_BASE + 147), "Issuer's Certificate Revocation List has an unknown version number.") ER3(SEC_ERROR_CRL_V1_CRITICAL_EXTENSION, (SEC_ERROR_BASE + 148), "Issuer's V1 Certificate Revocation List has a critical extension.") ER3(SEC_ERROR_CRL_UNKNOWN_CRITICAL_EXTENSION, (SEC_ERROR_BASE + 149), "Issuer's V2 Certificate Revocation List has an unknown critical extension.") ER3(SEC_ERROR_UNKNOWN_OBJECT_TYPE, (SEC_ERROR_BASE + 150), "Unknown object type specified.") ER3(SEC_ERROR_INCOMPATIBLE_PKCS11, (SEC_ERROR_BASE + 151), "PKCS #11 driver violates the spec in an incompatible way.") ER3(SEC_ERROR_NO_EVENT, (SEC_ERROR_BASE + 152), "No new slot event is available at this time.") ER3(SEC_ERROR_CRL_ALREADY_EXISTS, (SEC_ERROR_BASE + 153), "CRL already exists.") ER3(SEC_ERROR_NOT_INITIALIZED, (SEC_ERROR_BASE + 154), "NSS is not initialized.") ER3(SEC_ERROR_TOKEN_NOT_LOGGED_IN, (SEC_ERROR_BASE + 155), "The operation failed because the PKCS#11 token is not logged in.") ER3(SEC_ERROR_OCSP_RESPONDER_CERT_INVALID, (SEC_ERROR_BASE + 156), "Configured OCSP responder's certificate is invalid.") ER3(SEC_ERROR_OCSP_BAD_SIGNATURE, (SEC_ERROR_BASE + 157), "OCSP response has an invalid signature.") ER3(SEC_ERROR_OUT_OF_SEARCH_LIMITS, (SEC_ERROR_BASE + 158), "Cert validation search is out of search limits") ER3(SEC_ERROR_INVALID_POLICY_MAPPING, (SEC_ERROR_BASE + 159), "Policy mapping contains anypolicy") ER3(SEC_ERROR_POLICY_VALIDATION_FAILED, (SEC_ERROR_BASE + 160), "Cert chain fails policy validation") ER3(SEC_ERROR_UNKNOWN_AIA_LOCATION_TYPE, (SEC_ERROR_BASE + 161), "Unknown location type in cert AIA extension") ER3(SEC_ERROR_BAD_HTTP_RESPONSE, (SEC_ERROR_BASE + 162), "Server returned bad HTTP response") ER3(SEC_ERROR_BAD_LDAP_RESPONSE, (SEC_ERROR_BASE + 163), "Server returned bad LDAP response") ER3(SEC_ERROR_FAILED_TO_ENCODE_DATA, (SEC_ERROR_BASE + 164), "Failed to encode data with ASN1 encoder") ER3(SEC_ERROR_BAD_INFO_ACCESS_LOCATION, (SEC_ERROR_BASE + 165), "Bad information access location in cert extension") ER3(SEC_ERROR_LIBPKIX_INTERNAL, (SEC_ERROR_BASE + 166), "Libpkix internal error occured during cert validation.") ER3(SEC_ERROR_PKCS11_GENERAL_ERROR, (SEC_ERROR_BASE + 167), "A PKCS #11 module returned CKR_GENERAL_ERROR, indicating that an unrecoverable error has occurred.") ER3(SEC_ERROR_PKCS11_FUNCTION_FAILED, (SEC_ERROR_BASE + 168), "A PKCS #11 module returned CKR_FUNCTION_FAILED, indicating that the requested function could not be performed. Trying the same operation again might succeed.") ER3(SEC_ERROR_PKCS11_DEVICE_ERROR, (SEC_ERROR_BASE + 169), "A PKCS #11 module returned CKR_DEVICE_ERROR, indicating that a problem has occurred with the token or slot.") ER3(SEC_ERROR_BAD_INFO_ACCESS_METHOD, (SEC_ERROR_BASE + 170), "Unknown information access method in certificate extension.") ER3(SEC_ERROR_CRL_IMPORT_FAILED, (SEC_ERROR_BASE + 171), "Error attempting to import a CRL.") jss-5.0.0/src/main/java/org/mozilla/jss/util/SSLerrs.h000066400000000000000000000356671412550063600225120ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* SSL-specific security error codes */ /* caller must include "sslerr.h" */ ER3(SSL_ERROR_EXPORT_ONLY_SERVER, SSL_ERROR_BASE + 0, "Unable to communicate securely. Peer does not support high-grade encryption.") ER3(SSL_ERROR_US_ONLY_SERVER, SSL_ERROR_BASE + 1, "Unable to communicate securely. Peer requires high-grade encryption which is not supported.") ER3(SSL_ERROR_NO_CYPHER_OVERLAP, SSL_ERROR_BASE + 2, "Cannot communicate securely with peer: no common encryption algorithm(s).") ER3(SSL_ERROR_NO_CERTIFICATE, SSL_ERROR_BASE + 3, "Unable to find the certificate or key necessary for authentication.") ER3(SSL_ERROR_BAD_CERTIFICATE, SSL_ERROR_BASE + 4, "Unable to communicate securely with peer: peers's certificate was rejected.") /* unused (SSL_ERROR_BASE + 5),*/ ER3(SSL_ERROR_BAD_CLIENT, SSL_ERROR_BASE + 6, "The server has encountered bad data from the client.") ER3(SSL_ERROR_BAD_SERVER, SSL_ERROR_BASE + 7, "The client has encountered bad data from the server.") ER3(SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE, SSL_ERROR_BASE + 8, "Unsupported certificate type.") ER3(SSL_ERROR_UNSUPPORTED_VERSION, SSL_ERROR_BASE + 9, "Peer using unsupported version of security protocol.") /* unused (SSL_ERROR_BASE + 10),*/ ER3(SSL_ERROR_WRONG_CERTIFICATE, SSL_ERROR_BASE + 11, "Client authentication failed: private key in key database does not match public key in certificate database.") ER3(SSL_ERROR_BAD_CERT_DOMAIN, SSL_ERROR_BASE + 12, "Unable to communicate securely with peer: requested domain name does not match the server's certificate.") /* SSL_ERROR_POST_WARNING (SSL_ERROR_BASE + 13), defined in sslerr.h */ ER3(SSL_ERROR_SSL2_DISABLED, (SSL_ERROR_BASE + 14), "Peer only supports SSL version 2, which is locally disabled.") ER3(SSL_ERROR_BAD_MAC_READ, (SSL_ERROR_BASE + 15), "SSL received a record with an incorrect Message Authentication Code.") ER3(SSL_ERROR_BAD_MAC_ALERT, (SSL_ERROR_BASE + 16), "SSL peer reports incorrect Message Authentication Code.") ER3(SSL_ERROR_BAD_CERT_ALERT, (SSL_ERROR_BASE + 17), "SSL peer cannot verify your certificate.") ER3(SSL_ERROR_REVOKED_CERT_ALERT, (SSL_ERROR_BASE + 18), "SSL peer rejected your certificate as revoked.") ER3(SSL_ERROR_EXPIRED_CERT_ALERT, (SSL_ERROR_BASE + 19), "SSL peer rejected your certificate as expired.") ER3(SSL_ERROR_SSL_DISABLED, (SSL_ERROR_BASE + 20), "Cannot connect: SSL is disabled.") ER3(SSL_ERROR_FORTEZZA_PQG, (SSL_ERROR_BASE + 21), "Cannot connect: SSL peer is in another FORTEZZA domain.") ER3(SSL_ERROR_UNKNOWN_CIPHER_SUITE , (SSL_ERROR_BASE + 22), "An unknown SSL cipher suite has been requested.") ER3(SSL_ERROR_NO_CIPHERS_SUPPORTED , (SSL_ERROR_BASE + 23), "No cipher suites are present and enabled in this program.") ER3(SSL_ERROR_BAD_BLOCK_PADDING , (SSL_ERROR_BASE + 24), "SSL received a record with bad block padding.") ER3(SSL_ERROR_RX_RECORD_TOO_LONG , (SSL_ERROR_BASE + 25), "SSL received a record that exceeded the maximum permissible length.") ER3(SSL_ERROR_TX_RECORD_TOO_LONG , (SSL_ERROR_BASE + 26), "SSL attempted to send a record that exceeded the maximum permissible length.") /* * Received a malformed (too long or short or invalid content) SSL handshake. */ ER3(SSL_ERROR_RX_MALFORMED_HELLO_REQUEST , (SSL_ERROR_BASE + 27), "SSL received a malformed Hello Request handshake message.") ER3(SSL_ERROR_RX_MALFORMED_CLIENT_HELLO , (SSL_ERROR_BASE + 28), "SSL received a malformed Client Hello handshake message.") ER3(SSL_ERROR_RX_MALFORMED_SERVER_HELLO , (SSL_ERROR_BASE + 29), "SSL received a malformed Server Hello handshake message.") ER3(SSL_ERROR_RX_MALFORMED_CERTIFICATE , (SSL_ERROR_BASE + 30), "SSL received a malformed Certificate handshake message.") ER3(SSL_ERROR_RX_MALFORMED_SERVER_KEY_EXCH , (SSL_ERROR_BASE + 31), "SSL received a malformed Server Key Exchange handshake message.") ER3(SSL_ERROR_RX_MALFORMED_CERT_REQUEST , (SSL_ERROR_BASE + 32), "SSL received a malformed Certificate Request handshake message.") ER3(SSL_ERROR_RX_MALFORMED_HELLO_DONE , (SSL_ERROR_BASE + 33), "SSL received a malformed Server Hello Done handshake message.") ER3(SSL_ERROR_RX_MALFORMED_CERT_VERIFY , (SSL_ERROR_BASE + 34), "SSL received a malformed Certificate Verify handshake message.") ER3(SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH , (SSL_ERROR_BASE + 35), "SSL received a malformed Client Key Exchange handshake message.") ER3(SSL_ERROR_RX_MALFORMED_FINISHED , (SSL_ERROR_BASE + 36), "SSL received a malformed Finished handshake message.") /* * Received a malformed (too long or short) SSL record. */ ER3(SSL_ERROR_RX_MALFORMED_CHANGE_CIPHER , (SSL_ERROR_BASE + 37), "SSL received a malformed Change Cipher Spec record.") ER3(SSL_ERROR_RX_MALFORMED_ALERT , (SSL_ERROR_BASE + 38), "SSL received a malformed Alert record.") ER3(SSL_ERROR_RX_MALFORMED_HANDSHAKE , (SSL_ERROR_BASE + 39), "SSL received a malformed Handshake record.") ER3(SSL_ERROR_RX_MALFORMED_APPLICATION_DATA , (SSL_ERROR_BASE + 40), "SSL received a malformed Application Data record.") /* * Received an SSL handshake that was inappropriate for the state we're in. * E.g. Server received message from server, or wrong state in state machine. */ ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_REQUEST , (SSL_ERROR_BASE + 41), "SSL received an unexpected Hello Request handshake message.") ER3(SSL_ERROR_RX_UNEXPECTED_CLIENT_HELLO , (SSL_ERROR_BASE + 42), "SSL received an unexpected Client Hello handshake message.") ER3(SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO , (SSL_ERROR_BASE + 43), "SSL received an unexpected Server Hello handshake message.") ER3(SSL_ERROR_RX_UNEXPECTED_CERTIFICATE , (SSL_ERROR_BASE + 44), "SSL received an unexpected Certificate handshake message.") ER3(SSL_ERROR_RX_UNEXPECTED_SERVER_KEY_EXCH , (SSL_ERROR_BASE + 45), "SSL received an unexpected Server Key Exchange handshake message.") ER3(SSL_ERROR_RX_UNEXPECTED_CERT_REQUEST , (SSL_ERROR_BASE + 46), "SSL received an unexpected Certificate Request handshake message.") ER3(SSL_ERROR_RX_UNEXPECTED_HELLO_DONE , (SSL_ERROR_BASE + 47), "SSL received an unexpected Server Hello Done handshake message.") ER3(SSL_ERROR_RX_UNEXPECTED_CERT_VERIFY , (SSL_ERROR_BASE + 48), "SSL received an unexpected Certificate Verify handshake message.") ER3(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH , (SSL_ERROR_BASE + 49), "SSL received an unexpected Client Key Exchange handshake message.") ER3(SSL_ERROR_RX_UNEXPECTED_FINISHED , (SSL_ERROR_BASE + 50), "SSL received an unexpected Finished handshake message.") /* * Received an SSL record that was inappropriate for the state we're in. */ ER3(SSL_ERROR_RX_UNEXPECTED_CHANGE_CIPHER , (SSL_ERROR_BASE + 51), "SSL received an unexpected Change Cipher Spec record.") ER3(SSL_ERROR_RX_UNEXPECTED_ALERT , (SSL_ERROR_BASE + 52), "SSL received an unexpected Alert record.") ER3(SSL_ERROR_RX_UNEXPECTED_HANDSHAKE , (SSL_ERROR_BASE + 53), "SSL received an unexpected Handshake record.") ER3(SSL_ERROR_RX_UNEXPECTED_APPLICATION_DATA, (SSL_ERROR_BASE + 54), "SSL received an unexpected Application Data record.") /* * Received record/message with unknown discriminant. */ ER3(SSL_ERROR_RX_UNKNOWN_RECORD_TYPE , (SSL_ERROR_BASE + 55), "SSL received a record with an unknown content type.") ER3(SSL_ERROR_RX_UNKNOWN_HANDSHAKE , (SSL_ERROR_BASE + 56), "SSL received a handshake message with an unknown message type.") ER3(SSL_ERROR_RX_UNKNOWN_ALERT , (SSL_ERROR_BASE + 57), "SSL received an alert record with an unknown alert description.") /* * Received an alert reporting what we did wrong. (more alerts above) */ ER3(SSL_ERROR_CLOSE_NOTIFY_ALERT , (SSL_ERROR_BASE + 58), "SSL peer has closed this connection.") ER3(SSL_ERROR_HANDSHAKE_UNEXPECTED_ALERT , (SSL_ERROR_BASE + 59), "SSL peer was not expecting a handshake message it received.") ER3(SSL_ERROR_DECOMPRESSION_FAILURE_ALERT , (SSL_ERROR_BASE + 60), "SSL peer was unable to successfully decompress an SSL record it received.") ER3(SSL_ERROR_HANDSHAKE_FAILURE_ALERT , (SSL_ERROR_BASE + 61), "SSL peer was unable to negotiate an acceptable set of security parameters.") ER3(SSL_ERROR_ILLEGAL_PARAMETER_ALERT , (SSL_ERROR_BASE + 62), "SSL peer rejected a handshake message for unacceptable content.") ER3(SSL_ERROR_UNSUPPORTED_CERT_ALERT , (SSL_ERROR_BASE + 63), "SSL peer does not support certificates of the type it received.") ER3(SSL_ERROR_CERTIFICATE_UNKNOWN_ALERT , (SSL_ERROR_BASE + 64), "SSL peer had some unspecified issue with the certificate it received.") ER3(SSL_ERROR_GENERATE_RANDOM_FAILURE , (SSL_ERROR_BASE + 65), "SSL experienced a failure of its random number generator.") ER3(SSL_ERROR_SIGN_HASHES_FAILURE , (SSL_ERROR_BASE + 66), "Unable to digitally sign data required to verify your certificate.") ER3(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE , (SSL_ERROR_BASE + 67), "SSL was unable to extract the public key from the peer's certificate.") ER3(SSL_ERROR_SERVER_KEY_EXCHANGE_FAILURE , (SSL_ERROR_BASE + 68), "Unspecified failure while processing SSL Server Key Exchange handshake.") ER3(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE , (SSL_ERROR_BASE + 69), "Unspecified failure while processing SSL Client Key Exchange handshake.") ER3(SSL_ERROR_ENCRYPTION_FAILURE , (SSL_ERROR_BASE + 70), "Bulk data encryption algorithm failed in selected cipher suite.") ER3(SSL_ERROR_DECRYPTION_FAILURE , (SSL_ERROR_BASE + 71), "Bulk data decryption algorithm failed in selected cipher suite.") ER3(SSL_ERROR_SOCKET_WRITE_FAILURE , (SSL_ERROR_BASE + 72), "Attempt to write encrypted data to underlying socket failed.") ER3(SSL_ERROR_MD5_DIGEST_FAILURE , (SSL_ERROR_BASE + 73), "MD5 digest function failed.") ER3(SSL_ERROR_SHA_DIGEST_FAILURE , (SSL_ERROR_BASE + 74), "SHA-1 digest function failed.") ER3(SSL_ERROR_MAC_COMPUTATION_FAILURE , (SSL_ERROR_BASE + 75), "MAC computation failed.") ER3(SSL_ERROR_SYM_KEY_CONTEXT_FAILURE , (SSL_ERROR_BASE + 76), "Failure to create Symmetric Key context.") ER3(SSL_ERROR_SYM_KEY_UNWRAP_FAILURE , (SSL_ERROR_BASE + 77), "Failure to unwrap the Symmetric key in Client Key Exchange message.") ER3(SSL_ERROR_PUB_KEY_SIZE_LIMIT_EXCEEDED , (SSL_ERROR_BASE + 78), "SSL Server attempted to use domestic-grade public key with export cipher suite.") ER3(SSL_ERROR_IV_PARAM_FAILURE , (SSL_ERROR_BASE + 79), "PKCS11 code failed to translate an IV into a param.") ER3(SSL_ERROR_INIT_CIPHER_SUITE_FAILURE , (SSL_ERROR_BASE + 80), "Failed to initialize the selected cipher suite.") ER3(SSL_ERROR_SESSION_KEY_GEN_FAILURE , (SSL_ERROR_BASE + 81), "Client failed to generate session keys for SSL session.") ER3(SSL_ERROR_NO_SERVER_KEY_FOR_ALG , (SSL_ERROR_BASE + 82), "Server has no key for the attempted key exchange algorithm.") ER3(SSL_ERROR_TOKEN_INSERTION_REMOVAL , (SSL_ERROR_BASE + 83), "PKCS#11 token was inserted or removed while operation was in progress.") ER3(SSL_ERROR_TOKEN_SLOT_NOT_FOUND , (SSL_ERROR_BASE + 84), "No PKCS#11 token could be found to do a required operation.") ER3(SSL_ERROR_NO_COMPRESSION_OVERLAP , (SSL_ERROR_BASE + 85), "Cannot communicate securely with peer: no common compression algorithm(s).") ER3(SSL_ERROR_HANDSHAKE_NOT_COMPLETED , (SSL_ERROR_BASE + 86), "Cannot initiate another SSL handshake until current handshake is complete.") ER3(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE , (SSL_ERROR_BASE + 87), "Received incorrect handshakes hash values from peer.") ER3(SSL_ERROR_CERT_KEA_MISMATCH , (SSL_ERROR_BASE + 88), "The certificate provided cannot be used with the selected key exchange algorithm.") ER3(SSL_ERROR_NO_TRUSTED_SSL_CLIENT_CA , (SSL_ERROR_BASE + 89), "No certificate authority is trusted for SSL client authentication.") ER3(SSL_ERROR_SESSION_NOT_FOUND , (SSL_ERROR_BASE + 90), "Client's SSL session ID not found in server's session cache.") ER3(SSL_ERROR_DECRYPTION_FAILED_ALERT , (SSL_ERROR_BASE + 91), "Peer was unable to decrypt an SSL record it received.") ER3(SSL_ERROR_RECORD_OVERFLOW_ALERT , (SSL_ERROR_BASE + 92), "Peer received an SSL record that was longer than is permitted.") ER3(SSL_ERROR_UNKNOWN_CA_ALERT , (SSL_ERROR_BASE + 93), "Peer does not recognize and trust the CA that issued your certificate.") ER3(SSL_ERROR_ACCESS_DENIED_ALERT , (SSL_ERROR_BASE + 94), "Peer received a valid certificate, but access was denied.") ER3(SSL_ERROR_DECODE_ERROR_ALERT , (SSL_ERROR_BASE + 95), "Peer could not decode an SSL handshake message.") ER3(SSL_ERROR_DECRYPT_ERROR_ALERT , (SSL_ERROR_BASE + 96), "Peer reports failure of signature verification or key exchange.") ER3(SSL_ERROR_EXPORT_RESTRICTION_ALERT , (SSL_ERROR_BASE + 97), "Peer reports negotiation not in compliance with export regulations.") ER3(SSL_ERROR_PROTOCOL_VERSION_ALERT , (SSL_ERROR_BASE + 98), "Peer reports incompatible or unsupported protocol version.") ER3(SSL_ERROR_INSUFFICIENT_SECURITY_ALERT , (SSL_ERROR_BASE + 99), "Server requires ciphers more secure than those supported by client.") ER3(SSL_ERROR_INTERNAL_ERROR_ALERT , (SSL_ERROR_BASE + 100), "Peer reports it experienced an internal error.") ER3(SSL_ERROR_USER_CANCELED_ALERT , (SSL_ERROR_BASE + 101), "Peer user canceled handshake.") ER3(SSL_ERROR_NO_RENEGOTIATION_ALERT , (SSL_ERROR_BASE + 102), "Peer does not permit renegotiation of SSL security parameters.") ER3(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED , (SSL_ERROR_BASE + 103), "SSL server cache not configured and not disabled for this socket.") ER3(SSL_ERROR_UNSUPPORTED_EXTENSION_ALERT , (SSL_ERROR_BASE + 104), "SSL peer does not support requested TLS hello extension.") ER3(SSL_ERROR_CERTIFICATE_UNOBTAINABLE_ALERT , (SSL_ERROR_BASE + 105), "SSL peer could not obtain your certificate from the supplied URL.") ER3(SSL_ERROR_UNRECOGNIZED_NAME_ALERT , (SSL_ERROR_BASE + 106), "SSL peer has no certificate for the requested DNS name.") ER3(SSL_ERROR_BAD_CERT_STATUS_RESPONSE_ALERT , (SSL_ERROR_BASE + 107), "SSL peer was unable to get an OCSP response for its certificate.") ER3(SSL_ERROR_BAD_CERT_HASH_VALUE_ALERT , (SSL_ERROR_BASE + 108), "SSL peer reported bad certificate hash value.") ER3(SSL_ERROR_RX_UNEXPECTED_NEW_SESSION_TICKET, (SSL_ERROR_BASE + 109), "SSL received an unexpected New Session Ticket handshake message.") ER3(SSL_ERROR_RX_MALFORMED_NEW_SESSION_TICKET, (SSL_ERROR_BASE + 110), "SSL received a malformed New Session Ticket handshake message.") ER3(SSL_ERROR_DECOMPRESSION_FAILURE, (SSL_ERROR_BASE + 111), "SSL received a compressed record that could not be decompressed.") ER3(SSL_ERROR_RENEGOTIATION_NOT_ALLOWED, (SSL_ERROR_BASE + 112), "Renegotiation is not allowed on this SSL socket.") jss-5.0.0/src/main/java/org/mozilla/jss/util/StaticVoidPointer.c000066400000000000000000000022671412550063600245500ustar00rootroot00000000000000#include #include #include "java_ids.h" #include "jssutil.h" jobject JSS_PR_wrapStaticVoidPointer(JNIEnv *env, void **ref) { jbyteArray pointer = NULL; jclass proxyClass; jmethodID constructor; jobject refObj = NULL; PR_ASSERT(env != NULL && ref != NULL && *ref != NULL); /* Convert pointer to byte array. */ pointer = JSS_ptrToByteArray(env, *ref); /* Lookup the class and constructor. */ proxyClass = (*env)->FindClass(env, STATIC_VOID_POINTER_CLASS_NAME); if (proxyClass == NULL) { ASSERT_OUTOFMEM(env); goto finish; } constructor = (*env)->GetMethodID(env, proxyClass, PLAIN_CONSTRUCTOR, STATIC_VOID_POINTER_CONSTRUCTOR_SIG); if (constructor == NULL) { ASSERT_OUTOFMEM(env); goto finish; } /* Call the constructor. */ refObj = (*env)->NewObject(env, proxyClass, constructor, pointer); finish: PR_ASSERT(refObj || (*env)->ExceptionOccurred(env)); return refObj; } PRStatus JSS_PR_getStaticVoidRef(JNIEnv *env, jobject ref_proxy, void **ref) { return JSS_getPtrFromProxy(env, ref_proxy, ref); } jss-5.0.0/src/main/java/org/mozilla/jss/util/StaticVoidPointer.h000066400000000000000000000002621412550063600245460ustar00rootroot00000000000000#include #include jobject JSS_PR_wrapStaticVoidPointer(JNIEnv *env, void **ref); PRStatus JSS_PR_getStaticVoidRef(JNIEnv *env, jobject ref_proxy, void **ref); jss-5.0.0/src/main/java/org/mozilla/jss/util/StaticVoidPointer.java000066400000000000000000000014631412550063600252440ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.util; /** * StaticVoidPointer is a Java class that mirror a statically allocated * `void *` pointer in C. * * This is helpful for implementing NativeEnclosure and preventing the * resulting pointer from getting tracked in the usual NativeProxy allocation * trackers and avoiding a double free. */ public class StaticVoidPointer extends NativeProxy { public StaticVoidPointer(byte[] pointer) { super(pointer, false); } @Override protected void releaseNativeResources() { /* Do nothing: this is a static pointer that doesn't need freeing. */ } } jss-5.0.0/src/main/java/org/mozilla/jss/util/Tunnel.java000066400000000000000000000006751412550063600231030ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.util; /** * A class to allow friendly functions access to other parts of JSS. */ public class Tunnel { protected static byte[] GetPasswordByteCopy(Password pw) { return pw.getByteCopy(); } } jss-5.0.0/src/main/java/org/mozilla/jss/util/UTF8Converter.java000066400000000000000000000230331412550063600242450ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.util; import java.io.CharConversionException; /** * Class for converting between char arrays and byte arrays. The conversion * is guaranteed (in optimized mode only) not to leave any data hanging around * in memory unless there is a catastrophic VM error, which is useful for * encoding passwords. */ public class UTF8Converter { /** * Creates a new UTF8-encoded byte array representing the * char[] passed in. The output array will NOT be null-terminated. * *

This call is safe for passwords; all internal buffers are cleared. * The output array is the owned by the caller, who has responsibility * for clearing it. * *

See http://www.stonehard.com/unicode/standard/ for the UTF-16 * and UTF-8 standards. * * @param unicode An array of Unicode characters, which may have UCS4 * characters encoded in UTF-16. This array must not be null. * @exception CharConversionException If the input characters are invalid. */ public static byte[] UnicodeToUTF8(char[] unicode) throws CharConversionException { return UnicodeToUTF8(unicode, false); } /** * Creates a new null-terminated UTF8-encoded byte array representing the * char[] passed in. * *

This call is safe for passwords; all internal buffers are cleared. * The output array is the owned by the caller, who has responsibility * for clearing it. * *

See http://www.stonehard.com/unicode/standard/ for the UTF-16 * and UTF-8 standards. * * @param unicode An array of Unicode characters, which may have UCS4 * characters encoded in UTF-16. This array must not be null. * @exception CharConversionException If the input characters are invalid. */ public static byte[] UnicodeToUTF8NullTerm(char [] unicode) throws CharConversionException { return UnicodeToUTF8(unicode, true); } /** * Do the work of the above functions. */ protected static byte[] UnicodeToUTF8(char[] unicode, boolean nullTerminate) throws CharConversionException { int uni; // unicode index int utf; // UTF8 index int maxsize; // maximum size of UTF8 output byte[] utf8 = null; // UTF8 output buffer byte[] temp = null; // used to create an array of the correct size char c; // Unicode character int ucs4; // UCS4 encoding of a character boolean failed = true; assert(unicode != null); if(unicode == null) { return null; } try { // Allocate worst-case size (UTF8 bytes == 1.5 times Unicode bytes) maxsize = unicode.length * 3; //chars are 2 bytes each if(nullTerminate) { maxsize++; } utf8 = new byte[maxsize]; for(uni=0, utf=0; uni < unicode.length; uni++) { // // Convert UCS2 to UCS4 // c = unicode[uni]; if( c >= 0xd800 && c <= 0xdbff) { // This is the high half of a UTF-16 char ucs4 = (c-0xd800)<<10; // Now get the lower half if(uni == unicode.length-1) { //There is no lower half throw new CharConversionException(); } c = unicode[++uni]; if(c < 0xdc00 || c > 0xdfff) { // not in the low-half zone throw new CharConversionException(); } ucs4 |= c-0xdc00; ucs4 += 0x00010000; } else if(c >=0xdc00 && c <=0xdfff) { // My class rejects orphaned low-half characters, but the Java // class allows them. I think they really are bogus, so // let's pretend the Java class rejects them too. throw new CharConversionException("Orphaned low-half character: 0x" + Integer.toHexString(c)); } else { // UCS2 char to UCS4 ucs4 = unicode[uni]; } // // UCS4 to UTF8 conversion // if(ucs4 < 0x80) { // 0000 0000 - 0000 007f (ASCII) utf8[utf++] = (byte)ucs4; } else if(ucs4 < 0x800) { // 0000 0080 - 0000 07ff utf8[utf++] = (byte) (0xc0 | ucs4>>6); utf8[utf++] = (byte) (0x80 | (ucs4 & 0x3f) ); } else if(ucs4 < 0x0010000) { // 0000 0800 - 0000 ffff utf8[utf++] = (byte) (0xe0 | ucs4>>12); utf8[utf++] = (byte) (0x80 | ((ucs4>>6) & 0x3f) ); utf8[utf++] = (byte) (0x80 | (ucs4 & 0x3f) ); } else if(ucs4 < 0x00200000) { // 001 0000 - 001f ffff utf8[utf++] = (byte) (0xf0 | ucs4>>18); utf8[utf++] = (byte) (0x80 | ((ucs4>>12) & 0x3f) ); utf8[utf++] = (byte) (0x80 | ((ucs4>>6) & 0x3f) ); utf8[utf++] = (byte) (0x80 | (ucs4 & 0x3f) ); } else if(ucs4 < 0x00200000) { // 0020 0000 - 03ff ffff utf8[utf++] = (byte) (0xf8 | ucs4>>24); utf8[utf++] = (byte) (0x80 | ((ucs4>>18) & 0x3f) ); utf8[utf++] = (byte) (0x80 | ((ucs4>>12) & 0x3f) ); utf8[utf++] = (byte) (0x80 | ((ucs4>>6) & 0x3f) ); utf8[utf++] = (byte) (0x80 | (ucs4 & 0x3f) ); } else { // 0400 0000 - 7fff ffff utf8[utf++] = (byte) (0xfc | ucs4>>30); utf8[utf++] = (byte) (0x80 | ((ucs4>>24) & 0x3f) ); utf8[utf++] = (byte) (0x80 | ((ucs4>>18) & 0x3f) ); utf8[utf++] = (byte) (0x80 | ((ucs4>>12) & 0x3f) ); utf8[utf++] = (byte) (0x80 | ((ucs4>>6) & 0x3f) ); utf8[utf++] = (byte) (0x80 | (ucs4 & 0x3f) ); } } if(nullTerminate) { utf8[utf++] = 0; } // // Copy into a correct-sized array // try { int i; // last index is the size of the UTF8 temp = new byte[utf]; for(i=0; i < utf; i++) { temp[i] = utf8[i]; utf8[i] = 0; } utf8 = temp; temp = null; } finally { if(temp != null) { wipeBytes(temp); } } failed = false; return utf8; } finally { // Cleanup data locations where the password was written if(failed && utf8 != null) { wipeBytes(utf8); utf8 = null; } ucs4 = 0; c = 0; } } /** * Wipes a byte array by setting all of its bytes to zero. * @param array The input array must not be null. */ public static void wipeBytes(byte[] array) { int i; assert(array != null); if(array == null) { return; } for(i=0; i < array.length; i++) { array[i] = 0; } } /** * Testing method */ public static void main(String[] args) { char[] unicode; byte[] utf8; int i, j; try { // // Regular ascii // System.out.println("ASCII Test:"); unicode = new char[128]; for(i=0; i< 128; i++) { unicode[i] = (char) i; } utf8 = UnicodeToUTF8(unicode); i = 0; while( i < 128) { for(j = i; j < 128 && j < i+20; j++) { System.out.print((int)unicode[j] + " "); } System.out.println(); for(j = i; j < 128 && j < i+20; j++) { System.out.print((int)utf8[j] + " "); } System.out.println("\n"); // two lines i = j; } // // UCS2 // System.out.println("UCS2 test:"); unicode = new char[] {'\u0000', '\u007f', '\u0080', '\u0400', '\u07ff', '\u0800', '\u3167', '\ud7ff', '\ue000', '\uffff'}; utf8 = UnicodeToUTF8(unicode); for(i=0; i<10; i++) { System.out.print( Integer.toHexString(unicode[i]) + " "); } System.out.println(); for(i=0; i "+utf8.length+ " bytes of utf8\n"); // // empty array // System.out.println("Empty input test:"); unicode = new char[0]; utf8 = UnicodeToUTF8(unicode); assert(utf8 != null); assert(utf8.length == 0); System.out.println("given 0 bytes Unicode, produces 0 length utf8\n"); // // UCS4 // System.out.println("UCS4 Test:"); unicode = new char[] {'\ud800', '\udc00', '\uda85', '\ude47', '\udbff', '\udfff'}; utf8 = UnicodeToUTF8(unicode); for(i=0; i < 6; i++) { System.out.print( Integer.toHexString(unicode[i]) + " "); } System.out.println(); for(i=0; i < utf8.length; i++) { System.out.print( Integer.toHexString(utf8[i]) + " "); } System.out.println("\n"); // // high half with no low half // System.out.println("high half at end of input:"); try { unicode = new char[] {'\ud800'}; utf8 = UnicodeToUTF8(unicode); throw new RuntimeException("should have failed on bad UCS4"); } catch (CharConversionException e) { System.out.println("Correctly caught bad UCS4\n"); } // // high half with something else // System.out.println("high half with something other than low half:"); try { unicode = new char[] {'\ud800', '\u007f'}; utf8 = UnicodeToUTF8(unicode); throw new RuntimeException("should have failed on bad UCS4"); } catch (CharConversionException e) { System.out.println("Correctly caught bad UCS4\n"); } // // orphaned low half // System.out.println("orphaned low half test:"); try { unicode = new char[] {'\u0032', '\udc01', '\u0033'}; utf8 = UnicodeToUTF8(unicode); throw new RuntimeException("should have failed on bad UCS4"); } catch (CharConversionException e) { System.out.println("Correctly caught bad UCS4\n"); } // // null-terminated // System.out.println("null-terminating:"); unicode = new char[] {'f', 'o', 'o', 'b', 'a', 'r'}; utf8 = UnicodeToUTF8NullTerm(unicode); for(i=0; i < unicode.length; i++) { System.out.print(unicode[i] + " "); } System.out.println(); for(i=0; i < utf8.length; i++) { System.out.print(utf8[i] + " "); } System.out.println("\n"); } catch(CharConversionException e) { System.out.println("Error converting Unicode "+e); } } } jss-5.0.0/src/main/java/org/mozilla/jss/util/errstrings.c000066400000000000000000000040061412550063600233310ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nspr.h" struct tuple_str { PRErrorCode errNum; const char * errString; }; typedef struct tuple_str tuple_str; #define ER2(a,b) {a, b}, #define ER3(a,b,c) {a, c}, #include "secerr.h" #include "sslerr.h" static const tuple_str errStrings[] = { /* keep this list in ascending order of error numbers */ #include "SSLerrs.h" #include "SECerrs.h" #include "NSPRerrs.h" }; static const PRInt32 numStrings = sizeof(errStrings) / sizeof(tuple_str); /* Returns a UTF-8 encoded constant error string for "errNum". * Returns NULL of errNum is unknown. */ const char * JSS_strerror(PRErrorCode errNum) { PRInt32 low = 0; PRInt32 high = numStrings - 1; PRInt32 i; PRErrorCode num; static int initDone; /* make sure table is in ascending order. * binary search depends on it. */ if (!initDone) { PRErrorCode lastNum = 0x80000000; for (i = low; i <= high; ++i) { num = errStrings[i].errNum; if (num <= lastNum) { fprintf(stderr, "sequence error in error strings at item %d\n" "error %d (%s)\n" "should come after \n" "error %d (%s)\n", i, lastNum, errStrings[i-1].errString, num, errStrings[i].errString); } lastNum = num; } initDone = 1; } /* Do binary search of table. */ while (low + 1 < high) { i = (low + high) / 2; num = errStrings[i].errNum; if (errNum == num) return errStrings[i].errString; if (errNum < num) high = i; else low = i; } if (errNum == errStrings[low].errNum) return errStrings[low].errString; if (errNum == errStrings[high].errNum) return errStrings[high].errString; return NULL; } jss-5.0.0/src/main/java/org/mozilla/jss/util/java_ids.h000066400000000000000000000300441412550063600227150ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef JAVA_IDS_H #define JAVA_IDS_H PR_BEGIN_EXTERN_C /* ** JNI uses strings to identify Java classes, fields, and methods. Rather ** than put lots of string constants in our JNI code, we define them once ** here. This has two benefits: it reduces the probability of typos ** (we only have to type the names once), and it allows us to more ** easily change these identifiers. */ #define PLAIN_CONSTRUCTOR "" #define PLAIN_CONSTRUCTOR_SIG "()V" /* * Algorithm */ #define ALGORITHM_CLASS_NAME "org/mozilla/jss/crypto/Algorithm" #define OID_INDEX_FIELD_NAME "oidIndex" #define OID_INDEX_FIELD_SIG "I" /* * BigInteger */ #define BIG_INTEGER_CLASS_NAME "java/math/BigInteger" #define BIG_INTEGER_CONSTRUCTOR_NAME "" #define BIG_INTEGER_CONSTRUCTOR_SIG "([B)V" /* * CipherContextProxy */ #define CIPHER_CONTEXT_PROXY_CLASS_NAME "org/mozilla/jss/pkcs11/CipherContextProxy" #define CIPHER_CONTEXT_PROXY_CONSTRUCTOR_SIG "([B)V" /* * Collection */ #define COLLECTION_CLASS_NAME "java/util/Collection" #define COLLECTION_ADD_NAME "add" #define COLLECTION_ADD_SIG "(Ljava/lang/Object;)Z" /* * InetAddress */ #define GET_ADDR_NAME "getAddress" #define GET_ADDR_SIG "()[B" /* * InputStream */ #define ISTREAM_READ_NAME "read" #define ISTREAM_READ_SIG "([B)I" /* * KeyPair */ #define KEY_PAIR_CLASS_NAME "java/security/KeyPair" #define KEY_PAIR_CONSTRUCTOR_NAME "" #define KEY_PAIR_CONSTRUCTOR_SIG "(Ljava/security/PublicKey;Ljava/security/PrivateKey;)V" /* * KeyProxy */ #define KEY_PROXY_FIELD "keyProxy" #define KEY_PROXY_SIG "Lorg/mozilla/jss/pkcs11/KeyProxy;" /* * KeyType */ #define KEYTYPE_CLASS_NAME "org/mozilla/jss/pkcs11/KeyType" #define NULL_KEYTYPE_FIELD "NULL" #define RSA_KEYTYPE_FIELD "RSA" #define DSA_KEYTYPE_FIELD "DSA" #define EC_KEYTYPE_FIELD "EC" #define FORTEZZA_KEYTYPE_FIELD "FORTEZZA" #define DH_KEYTYPE_FIELD "DH" #define KEA_KEYTYPE_FIELD "KEA" #define KEYTYPE_FIELD_SIG "Lorg/mozilla/jss/pkcs11/KeyType;" #define DES_KEYTYPE_FIELD "DES" #define DES3_KEYTYPE_FIELD "DES3" #define RC4_KEYTYPE_FIELD "RC4" #define RC2_KEYTYPE_FIELD "RC2" #define SHA1_HMAC_KEYTYPE_FIELD "SHA1_HMAC" #define AES_KEYTYPE_FIELD "AES" #define GENERIC_SECRET_KEYTYPE_FIELD "GENERIC_SECRET" /* * NativeProxy */ #define NATIVE_PROXY_CLASS_NAME "org/mozilla/jss/util/NativeProxy" #define NATIVE_PROXY_POINTER_FIELD "mPointer" #define NATIVE_PROXY_POINTER_SIG "[B" /* * NSSInit */ #define NSSINIT_CLASS_NAME "org/mozilla/jss/NSSInit" #define NSSINIT_ISINITIALIZED_NAME "isInitialized" #define NSSINIT_ISINITIALIZED_SIG "()Z" /* * OutputStream */ #define OSTREAM_WRITE_NAME "write" #define OSTREAM_WRITE_SIG "([BII)V" /* * Password */ #define PASSWORD_CLASS_NAME "org/mozilla/jss/util/Password" #define PASSWORD_CONSTRUCTOR_SIG "([C)V" #define PW_GET_BYTE_COPY_NAME "getByteCopy" #define PW_GET_BYTE_COPY_SIG "()[B" #define PW_CLEAR_NAME "clear" #define PW_CLEAR_SIG "()V" /* * PasswordCallback */ #define PW_CALLBACK_GET_PW_FIRST_NAME "getPasswordFirstAttempt" #define PW_CALLBACK_GET_PW_FIRST_SIG "(Lorg/mozilla/jss/util/PasswordCallbackInfo;)Lorg/mozilla/jss/util/Password;" #define PW_CALLBACK_GET_PW_AGAIN_NAME "getPasswordAgain" #define PW_CALLBACK_GET_PW_AGAIN_SIG "(Lorg/mozilla/jss/util/PasswordCallbackInfo;)Lorg/mozilla/jss/util/Password;" /* * PK11Cert */ #define CERT_CLASS_NAME "org/mozilla/jss/pkcs11/PK11Cert" #define CERT_CONSTRUCTOR_NAME "" #define CERT_CONSTRUCTOR_SIG "([B[BLjava/lang/String;)V" #define CERT_PROXY_FIELD "certProxy" #define CERT_PROXY_SIG "Lorg/mozilla/jss/pkcs11/CertProxy;" /* * PK11InternalCert */ #define INTERNAL_CERT_CLASS_NAME "org/mozilla/jss/pkcs11/PK11InternalCert" /* * PK11TokenCert */ #define TOKEN_CERT_CLASS_NAME "org/mozilla/jss/pkcs11/PK11TokenCert" /* * PK11InternalTokenCert */ #define INTERNAL_TOKEN_CERT_CLASS_NAME "org/mozilla/jss/pkcs11/PK11InternalTokenCert" /* * PK11DSAPublicKey */ #define PK11_DSA_PUBKEY_CLASS_NAME "org/mozilla/jss/pkcs11/PK11DSAPublicKey" /* * PK11ECPublicKey */ #define PK11_EC_PUBKEY_CLASS_NAME "org/mozilla/jss/pkcs11/PK11ECPublicKey" /* * PK11Module */ #define PK11MODULE_CLASS_NAME "org/mozilla/jss/pkcs11/PK11Module" #define PK11MODULE_CONSTRUCTOR_SIG "([B)V" #define PK11MODULE_PROXY_FIELD "moduleProxy" #define PK11MODULE_PROXY_SIG "Lorg/mozilla/jss/pkcs11/ModuleProxy;" /* * PK11PrivKey */ #define PK11PRIVKEY_CLASS_NAME "org/mozilla/jss/pkcs11/PK11PrivKey" #define PK11PRIVKEY_CONSTRUCTOR_NAME "" #define PK11PRIVKEY_CONSTRUCTOR_SIG "([B)V" /* * PK11PubKey */ #define PK11PUBKEY_CLASS_NAME "org/mozilla/jss/pkcs11/PK11PubKey" #define PK11PUBKEY_CONSTRUCTOR_NAME "" #define PK11PUBKEY_CONSTRUCTOR_SIG "([B)V" /* * PK11RSAPublicKey */ #define PK11_RSA_PUBKEY_CLASS_NAME "org/mozilla/jss/pkcs11/PK11RSAPublicKey" /* * PK11Signature */ #define PK11SIGNATURE_CLASS_NAME "org/mozilla/jss/pkcs11/PK11Signature" #define SIG_CONTEXT_PROXY_FIELD "sigContext" #define SIG_CONTEXT_PROXY_SIG "Lorg/mozilla/jss/pkcs11/SigContextProxy;" #define SIG_ALGORITHM_FIELD "algorithm" #define SIG_DIGEST_ALGORITHM_FIELD "digestAlgorithm" #define SIG_ALGORITHM_SIG "Lorg/mozilla/jss/crypto/Algorithm;" #define SIG_PW_FIELD "pwExtractor" #define SIG_PW_SIG "Lorg/mozilla/jss/crypto/PasswordExtractor;" #define SIG_KEY_FIELD "key" #define SIG_KEY_SIG "Lorg/mozilla/jss/pkcs11/PK11Key;" /* * PK11Store */ #define PK11STORE_PROXY_FIELD "storeProxy" #define PK11STORE_PROXY_SIG "Lorg/mozilla/jss/pkcs11/TokenProxy;" /* * PK11SymKey */ #define PK11SYMKEY_CLASS_NAME "org/mozilla/jss/pkcs11/PK11SymKey" #define PK11SYMKEY_CONSTRUCTOR_SIG "([B)V" #define PK11SYMKEY_CONSTRUCTOR_1_SIG "([BLjava/lang/String;)V" /* * PK11Token */ #define PK11TOKEN_PROXY_FIELD "tokenProxy" #define PK11TOKEN_PROXY_SIG "Lorg/mozilla/jss/pkcs11/TokenProxy;" #define PK11TOKEN_CLASS_NAME "org/mozilla/jss/pkcs11/PK11Token" #define PK11TOKEN_CONSTRUCTOR_NAME "" #define PK11TOKEN_CONSTRUCTOR_SIG "([BZZ)V" /* * PrivateKey.KeyType */ #define PRIVKEYTYPE_CLASS_NAME "org/mozilla/jss/crypto/PrivateKey$Type" #define PRIVKEYTYPE_SIG "Lorg/mozilla/jss/crypto/PrivateKey$Type;" #define RSA_PRIVKEYTYPE_FIELD "RSA" #define DSA_PRIVKEYTYPE_FIELD "DSA" #define EC_PRIVKEYTYPE_FIELD "EC" /* * PQGParams */ #define PQG_PARAMS_CONSTRUCTOR_NAME "" #define PQG_PARAMS_CONSTRUCTOR_SIG "(Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;ILjava/math/BigInteger;)V" /* * SigContextProxy */ #define SIG_CONTEXT_PROXY_CLASS_NAME "org/mozilla/jss/pkcs11/SigContextProxy" #define SIG_CONTEXT_PROXY_CONSTRUCTOR_NAME "" #define SIG_CONTEXT_PROXY_CONSTRUCTOR_SIG "([B)V" /* * Socket */ #define SOCKET_GET_OUTPUT_STREAM_NAME "getOutputStream" #define SOCKET_GET_OUTPUT_STREAM_SIG "()Ljava/io/OutputStream;" #define SOCKET_GET_INPUT_STREAM_NAME "getInputStream" #define SOCKET_GET_INPUT_STREAM_SIG "()Ljava/io/InputStream;" #define GET_INET_ADDR_NAME "getInetAddress" #define GET_INET_ADDR_SIG "()Ljava/net/InetAddress;" #define GET_PORT_NAME "getPort" #define GET_PORT_SIG "()I" #define GET_LOCAL_ADDR_NAME "getLocalAddress" #define GET_LOCAL_PORT_NAME "getLocalPort" #define SOCKET_CLOSE_NAME "close" #define SOCKET_CLOSE_SIG "()V" #define SET_SO_TIMEOUT_NAME "setSoTimeout" #define SET_SO_TIMEOUT_SIG "(I)V" #define GET_KEEPALIVE_NAME "getKeepAlive" #define GET_KEEPALIVE_SIG "()Z" #define GET_SEND_BUF_SIZE "getSendBufferSize" #define GET_RECV_BUF_SIZE "getReceiveBufferSize" #define GET_BUF_SIZE_SIG "()I" /* * CryptoManager * */ #define CRYPTO_MANAGER_NAME "org/mozilla/jss/CryptoManager" #define GET_OCSP_POLICY_NAME "getOCSPPolicy" #define GET_OCSP_POLICY_SIG "()I" /* * SocketBase */ #define SOCKET_BASE_NAME "org/mozilla/jss/ssl/SocketBase" #define PROCESS_EXCEPTIONS_NAME "processExceptions" #define PROCESS_EXCEPTIONS_SIG "(Ljava/lang/Throwable;Ljava/lang/Throwable;)Ljava/lang/Throwable;" #define SUPPORTS_IPV6_NAME "supportsIPV6" #define SUPPORTS_IPV6_SIG "()Z" /* * SSLAlertEvent */ #define SSL_ALERT_EVENT_CLASS "org/mozilla/jss/ssl/SSLAlertEvent" /* * SSLCertificateApprovalCallback */ #define SSLCERT_APP_CB_APPROVE_NAME "approve" #define SSLCERT_APP_CB_APPROVE_SIG "(Lorg/mozilla/jss/crypto/X509Certificate;Lorg/mozilla/jss/ssl/SSLCertificateApprovalCallback$ValidityStatus;)Z" /* * SSLSecurityStatus */ #define SSL_SECURITY_STATUS_CLASS_NAME "org/mozilla/jss/ssl/SSLSecurityStatus" #define SSL_SECURITY_STATUS_CONSTRUCTOR_NAME "" #define SSL_SECURITY_STATUS_CONSTRUCTOR_SIG "(ILjava/lang/String;IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Lorg/mozilla/jss/crypto/X509Certificate;)V" /* * SSLSocket */ #define SSLSOCKET_CLASS "org/mozilla/jss/ssl/SSLSocket" #define SSLSOCKET_HANDSHAKE_NOTIFIER_NAME "notifyAllHandshakeListeners" #define SSLSOCKET_HANDSHAKE_NOTIFIER_SIG "()V" #define SSLSOCKET_PROXY_FIELD "sockProxy" #define SSLSOCKET_PROXY_SIG "Lorg/mozilla/jss/ssl/SocketProxy;" /* * StringBuffer */ #define STRING_BUFFER_NAME "java/lang/StringBuffer" #define STRING_BUFFER_APPEND_NAME "append" #define STRING_BUFFER_APPEND_SIG "(Ljava/lang/String;)Ljava/lang/StringBuffer;" /* * ValidityStatus */ #define SSLCERT_APP_CB_VALIDITY_STATUS_CLASS \ "org/mozilla/jss/ssl/SSLCertificateApprovalCallback$ValidityStatus" #define SSLCERT_APP_CB_VALIDITY_STATUS_ADD_REASON_NAME "addReason" #define SSLCERT_APP_CB_VALIDITY_STATUS_ADD_REASON_SIG \ "(ILorg/mozilla/jss/pkcs11/PK11Cert;I)V" /* * SymKeyProxy */ #define SYM_KEY_PROXY_FIELD "keyProxy" #define SYM_KEY_PROXY_SIG "Lorg/mozilla/jss/pkcs11/SymKeyProxy;" /* * Throwable */ #define THROWABLE_NAME "java/lang/Throwable" #define THROWABLE_TO_STRING_NAME "toString" #define THROWABLE_TO_STRING_SIG "()Ljava/lang/String;" /* * TokenCallbackInfo */ #define TOKEN_CBINFO_CLASS_NAME "org/mozilla/jss/pkcs11/TokenCallbackInfo" #define TOKEN_CBINFO_CONSTRUCTOR_NAME "" #define TOKEN_CBINFO_CONSTRUCTOR_SIG "(Ljava/lang/String;)V" /* * Vector */ #define VECTOR_ADD_ELEMENT_NAME "addElement" #define VECTOR_ADD_ELEMENT_SIG "(Ljava/lang/Object;)V" /* * X509Certificate */ #define X509_CERT_CLASS "org/mozilla/jss/crypto/X509Certificate" /* * SSLVersionRange */ #define SSL_VERSION_RANGE_CLASS_NAME "org/mozilla/jss/ssl/SSLVersionRange" #define SSL_VERSION_RANGE_CONSTRUCTOR_NAME "" #define SSL_VERSION_RANGE_CONSTRUCTOR_SIG "(II)V" /* * PRFDProxy */ #define PRFD_PROXY_CLASS_NAME "org/mozilla/jss/nss/PRFDProxy" #define PRFD_PROXY_CONSTRUCTOR_SIG "([B)V" /* * SSLFDProxy */ #define SSLFD_PROXY_CLASS_NAME "org/mozilla/jss/nss/SSLFDProxy" #define SSLFD_PROXY_CONSTRUCTOR_SIG "([B)V" #define SSLFD_PROXY_CLIENT_CERT_FIELD "clientCert" #define SSLFD_PROXY_CLIENT_CERT_SIG "Lorg/mozilla/jss/pkcs11/PK11Cert;" #define SSLFD_PROXY_EVENT_LIST_SIG "Ljava/util/ArrayList;" /* * SecurityStatusResult */ #define SECURITY_STATUS_CLASS_NAME "org/mozilla/jss/nss/SecurityStatusResult" #define SECURITY_STATUS_CONSTRUCTOR_SIG "(I[BII[B[B)V" /* * BufferProxy */ #define BUFFER_PROXY_CLASS_NAME "org/mozilla/jss/nss/BufferProxy" #define BUFFER_PROXY_CONSTRUCTOR_SIG "([B)V" /* * GlobalRefProxy */ #define GLOBAL_REF_PROXY_CLASS_NAME "org/mozilla/jss/util/GlobalRefProxy" #define GLOBAL_REF_CONSTRUCTOR_SIG "([B)V" /* * StaticVoidProxy */ #define STATIC_VOID_POINTER_CLASS_NAME "org/mozilla/jss/util/StaticVoidPointer" #define STATIC_VOID_POINTER_CONSTRUCTOR_SIG "([B)V" /* * PKCS#11 CKAttribute */ #define CK_ATTRIBUTE_CLASS_NAME "org/mozilla/jss/pkcs11/attrs/CKAttribute" /* * KBKDF classes */ #define KBKDF_DATA_PARAMETER_CLASS_NAME "org/mozilla/jss/crypto/KBKDFDataParameter" #define KBKDF_DERIVED_KEY_CLASS_NAME "org/mozilla/jss/crypto/KBKDFDerivedKey" /* * SSLChannelInfo classes */ #define SSL_CHANNEL_INFO_CLASS_NAME "org/mozilla/jss/nss/SSLChannelInfo" #define SSL_CHANNEL_INFO_CONSTRUCTOR_SIG "(IIIIJJJ[BIZZIIIIIIZIZZZ)V" /* * SSLPreliminaryChannelInfo classes */ #define SSL_PRELIMINARY_CHANNEL_INFO_CLASS_NAME "org/mozilla/jss/nss/SSLPreliminaryChannelInfo" #define SSL_PRELIMINARY_CHANNEL_INFO_CONSTRUCTOR_SIG "(JIIZJZIZZII)V" PR_END_EXTERN_C #endif jss-5.0.0/src/main/java/org/mozilla/jss/util/jss_bigint.h000066400000000000000000000030751412550063600232740ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* Need to include these first: #include #include */ #ifndef JSS_BIG_INT_H #define JSS_BIG_INT_H PR_BEGIN_EXTERN_C /*********************************************************************** * * J S S _ O c t e t S t r i n g T o B y t e A r r a y * * Converts a representation of an integer as a big-endian octet string * stored in a SECItem (as used by the low-level crypto functions) to a * representation of an integer as a big-endian Java byte array. Prepends * a zero byte to force it to be positive. */ jbyteArray JSS_OctetStringToByteArray(JNIEnv *env, SECItem *item); /*********************************************************************** * * J S S _ B y t e A r r a y T o O c t e t S t r i n g * * Converts an integer represented as a big-endian Java byte array to * an integer represented as a big-endian octet string in a SECItem. * * INPUTS * byteArray * A Java byte array containing an integer represented in * big-endian format. Must not be NULL. * item * Pointer to a SECItem that will be filled with the integer * from the byte array, in big-endian format. * RETURNS * PR_SUCCESS if the operation was successful, PR_FAILURE if an exception * was thrown. */ PRStatus JSS_ByteArrayToOctetString(JNIEnv *env, jbyteArray byteArray, SECItem *item); PR_END_EXTERN_C #endif jss-5.0.0/src/main/java/org/mozilla/jss/util/jss_exceptions.h000066400000000000000000000101471412550063600241770ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* These are class names suitable for passing to JSS_nativeThrow or ** JSS_nativeThrowMsg. They are the fully qualified class name of the ** exception, separated by slashes instead of periods. */ #ifndef JSS_EXCEPTIONS_H #define JSS_EXCEPTIONS_H PR_BEGIN_EXTERN_C #define JAVA_LANG_EXCEPTION "java/lang/Exception" #define ALREADY_INITIALIZED_EXCEPTION "org/mozilla/jss/crypto/AlreadyInitializedException" #define ARRAY_INDEX_OUT_OF_BOUNDS_EXCEPTION "java/lang/ArrayIndexOutOfBoundsException" #define INDEX_OUT_OF_BOUNDS_EXCEPTION "java/lang/IndexOutOfBoundsException" #define BAD_PADDING_EXCEPTION "javax/crypto/BadPaddingException" #define BIND_EXCEPTION "java/net/BindException" #define CERT_DATABASE_EXCEPTION "org/mozilla/jss/CertDatabaseException" #define CERTIFICATE_EXCEPTION "java/security/cert/CertificateException" #define CERTIFICATE_ENCODING_EXCEPTION "java/security/cert/CertificateEncodingException" #define CERTIFICATE_EXPIRED_EXCEPTION "java/security/cert/CertificateExpiredException" #define CERTIFICATE_NOT_YET_VALID_EXCEPTION "java/security/cert/CertificateNotYetValidException" #define CERTIFICATE_PARSING_EXCEPTION "java/security/cert/CertificateParsingException" #define CERTIFICATE_REVOKED_EXCEPTION "java/security/cert/CertificateRevokedException" #define CRL_IMPORT_EXCEPTION "org/mozilla/jss/CRLImportException" #define DIGEST_EXCEPTION "java/security/DigestException" #define GENERAL_SECURITY_EXCEPTION "java/security/GeneralSecurityException" #define GENERIC_EXCEPTION "java/lang/Exception" #define GIVE_UP_EXCEPTION "org/mozilla/jss/util/PasswordCallback$GiveUpException" #define ILLEGAL_ARGUMENT_EXCEPTION "java/lang/IllegalArgumentException" #define ILLEGAL_BLOCK_SIZE_EXCEPTION "org/mozilla/jss/crypto/IllegalBlockSizeException" #define INCORRECT_PASSWORD_EXCEPTION "org/mozilla/jss/util/IncorrectPasswordException" #define INTERRUPTED_IO_EXCEPTION "java/io/InterruptedIOException" #define INVALID_DER_EXCEPTION "org/mozilla/jss/crypto/InvalidDERException" #define INVALID_NICKNAME_EXCEPTION "org/mozilla/jss/util/InvalidNicknameException" #define INVALID_KEY_FORMAT_EXCEPTION "org/mozilla/jss/crypto/InvalidKeyFormatException" #define INVALID_PARAMETER_EXCEPTION "java/security/InvalidParameterException" #define IO_EXCEPTION "java/io/IOException" #define KEY_DATABASE_EXCEPTION "org/mozilla/jss/KeyDatabaseException" #define KEY_EXISTS_EXCEPTION "org/mozilla/jss/crypto/KeyAlreadyImportedException" #define KEYSTORE_EXCEPTION "java/security/KeyStoreException" #define NICKNAME_CONFLICT_EXCEPTION "org/mozilla/jss/NicknameConflictException" #define NO_SUCH_ALG_EXCEPTION "java/security/NoSuchAlgorithmException" #define NO_SUCH_ITEM_ON_TOKEN_EXCEPTION "org/mozilla/jss/crypto/NoSuchItemOnTokenException" #define NO_SUCH_TOKEN_EXCEPTION "org/mozilla/jss/NoSuchTokenException" #define NOT_EXTRACTABLE_EXCEPTION "org/mozilla/jss/crypto/SymmetricKey$NotExtractableException" #define NULL_POINTER_EXCEPTION "java/lang/NullPointerException" #define OBJECT_NOT_FOUND_EXCEPTION "org/mozilla/jss/crypto/ObjectNotFoundException" #define OUT_OF_MEMORY_ERROR "java/lang/OutOfMemoryError" #define PK11_EXCEPTION "org/mozilla/jss/pkcs11/PK11Exception" #define PQG_PARAM_GEN_EXCEPTION "org/mozilla/jss/crypto/PQGParamGenException" /* This is a RuntimeException */ #define SECURITY_EXCEPTION "java/lang/SecurityException" #define SIGNATURE_EXCEPTION "java/security/SignatureException" #define SOCKET_EXCEPTION "java/net/SocketException" #define SSLSOCKET_EXCEPTION "org/mozilla/jss/ssl/SSLSocketException" #define SOCKET_TIMEOUT_EXCEPTION "java/net/SocketTimeoutException" #define TOKEN_EXCEPTION "org/mozilla/jss/crypto/TokenException" #define TOKEN_NOT_INITIALIZED_EXCEPTION "org/mozilla/jss/pkcs11/PK11Token$NotInitializedException" #define USER_CERT_CONFLICT_EXCEPTION "org/mozilla/jss/UserCertConflictException" #define UNSUPPORTED_OPERATION_EXCEPTION "java/lang/UnsupportedOperationException" PR_END_EXTERN_C #endif jss-5.0.0/src/main/java/org/mozilla/jss/util/jssutil.c000066400000000000000000001075501412550063600226340ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include "jssutil.h" #include "jss_bigint.h" #include "jss_exceptions.h" #include "java_ids.h" #include "nss.h" #include "cert.h" #include "certt.h" #include "pk11util.h" #include "secerr.h" #include "keyhi.h" /*********************************************************************** ** ** J S S _ t h r o w M s g P r E r r A r g ** ** Throw an exception in native code. You should return right after ** calling this function. ** ** throwableClassName is the name of the throwable you are throwing in ** JNI class name format (xxx/xx/xxx/xxx). It must not be NULL. ** ** message is the message parameter of the throwable. It must not be NULL. ** If you don't have a message, call JSS_throw. ** ** errCode is a PRErrorCode returned from PR_GetError(). ** ** Example: ** JSS_throwMsg(env, ILLEGAL_ARGUMENT_EXCEPTION, PR_GetError()); ** return -1; */ void JSS_throwMsgPrErrArg(JNIEnv *env, const char *throwableClassName, const char *message, PRErrorCode errCode) { const char *errStr = JSS_strerror(errCode); char *msg = NULL; int msgLen; if( errStr == NULL ) { errStr = "Unknown error"; } msgLen = strlen(message) + strlen(errStr) + 40; msg = PR_Malloc(msgLen); if( msg == NULL ) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } PR_snprintf(msg, msgLen, "%s: (%ld) %s", message, errCode, errStr); JSS_throwMsg(env, throwableClassName, msg); finish: if(msg != NULL) { PR_Free(msg); } } /*********************************************************************** ** ** J S S _ t h r o w M s g ** ** Throw an exception in native code. You should return right after ** calling this function. ** ** throwableClassName is the name of the throwable you are throwing in ** JNI class name format (xxx/xx/xxx/xxx). It must not be NULL. ** ** message is the message parameter of the throwable. It must not be NULL. ** If you don't have a message, call JSS_throw. ** ** Example: ** JSS_throwMsg(env, ILLEGAL_ARGUMENT_EXCEPTION, ** "Bogus argument, you ninny"); ** return -1; */ void JSS_throwMsg(JNIEnv *env, const char *throwableClassName, const char *message) { jclass throwableClass; jint VARIABLE_MAY_NOT_BE_USED result; /* validate arguments */ PR_ASSERT(env!=NULL && throwableClassName!=NULL && message!=NULL); throwableClass = NULL; if(throwableClassName) { throwableClass = (*env)->FindClass(env, throwableClassName); /* make sure the class was found */ PR_ASSERT(throwableClass != NULL); } if(throwableClass == NULL) { throwableClass = (*env)->FindClass(env, GENERIC_EXCEPTION); } PR_ASSERT(throwableClass != NULL); result = (*env)->ThrowNew(env, throwableClass, message); PR_ASSERT(result == 0); } /*********************************************************************** ** ** J S S _ t h r o w ** ** Throw an exception in native code. You should return right after ** calling this function. ** ** throwableClassName is the name of the throwable you are throwing in ** JNI class name format (xxx/xx/xxx/xxx). It must not be NULL. ** ** Example: ** JSS_throw(env, ILLEGAL_ARGUMENT_EXCEPTION); ** return -1; */ void JSS_throw(JNIEnv *env, char *throwableClassName) { jclass throwableClass; jobject throwable; jmethodID constructor; jint VARIABLE_MAY_NOT_BE_USED result; PR_ASSERT( (*env)->ExceptionOccurred(env) == NULL ); /* Lookup the class */ throwableClass = NULL; if(throwableClassName) { throwableClass = (*env)->FindClass(env, throwableClassName); /* make sure the class was found */ PR_ASSERT(throwableClass != NULL); } if(throwableClass == NULL) { throwableClass = (*env)->FindClass(env, GENERIC_EXCEPTION); } PR_ASSERT(throwableClass != NULL); /* Lookup up the plain vanilla constructor */ constructor = (*env)->GetMethodID( env, throwableClass, PLAIN_CONSTRUCTOR, PLAIN_CONSTRUCTOR_SIG); if(constructor == NULL) { /* Anything other than OutOfMemory is a bug */ ASSERT_OUTOFMEM(env); return; } /* Create an instance of the throwable */ throwable = (*env)->NewObject(env, throwableClass, constructor); if(throwable == NULL) { /* Anything other than OutOfMemory is a bug */ ASSERT_OUTOFMEM(env); return; } /* Throw the new instance */ result = (*env)->Throw(env, throwable); PR_ASSERT(result == 0); } /*********************************************************************** ** ** J S S _ g e t P t r F r o m P r o x y ** ** Given a NativeProxy, extract the pointer and store it at the given ** address. ** ** nativeProxy: a JNI reference to a NativeProxy. ** ptr: address of a void* that will receive the pointer extracted from ** the NativeProxy. ** Returns: PR_SUCCESS on success, PR_FAILURE if an exception was thrown. ** ** Example: ** DataStructure *recovered; ** jobject proxy; ** JNIEnv *env; ** [...] ** if(JSS_getPtrFromProxy(env, proxy, (void**)&recovered) != PR_SUCCESS) { ** return; // exception was thrown! ** } */ PRStatus JSS_getPtrFromProxy(JNIEnv *env, jobject nativeProxy, void **ptr) { #ifdef DEBUG jclass nativeProxyClass; #endif jclass proxyClass; jfieldID byteArrayField; jbyteArray byteArray; int size; PR_ASSERT(env!=NULL && nativeProxy != NULL && ptr != NULL); if( nativeProxy == NULL ) { JSS_throw(env, NULL_POINTER_EXCEPTION); return PR_FAILURE; } proxyClass = (*env)->GetObjectClass(env, nativeProxy); PR_ASSERT(proxyClass != NULL); #ifdef DEBUG nativeProxyClass = (*env)->FindClass( env, NATIVE_PROXY_CLASS_NAME); if(nativeProxyClass == NULL) { ASSERT_OUTOFMEM(env); return PR_FAILURE; } /* make sure what we got was really a NativeProxy object */ PR_ASSERT( (*env)->IsInstanceOf(env, nativeProxy, nativeProxyClass) ); #endif byteArrayField = (*env)->GetFieldID( env, proxyClass, NATIVE_PROXY_POINTER_FIELD, NATIVE_PROXY_POINTER_SIG); if(byteArrayField==NULL) { ASSERT_OUTOFMEM(env); return PR_FAILURE; } byteArray = (jbyteArray) (*env)->GetObjectField(env, nativeProxy, byteArrayField); if (byteArray == NULL) { *ptr = NULL; } else { size = sizeof(*ptr); PR_ASSERT((*env)->GetArrayLength(env, byteArray) == size); (*env)->GetByteArrayRegion(env, byteArray, 0, size, (void*)ptr); } if( (*env)->ExceptionOccurred(env) ) { PR_ASSERT(PR_FALSE); return PR_FAILURE; } else { return PR_SUCCESS; } } /*********************************************************************** ** ** J S S _ g e t P t r F r o m P r o x y O w n e r ** ** Given an object which contains a NativeProxy, extract the pointer ** from the NativeProxy and store it at the given address. ** ** proxyOwner: an object which contains a NativeProxy member. ** proxyFieldName: the name of the NativeProxy member. ** proxyFieldSig: the signature of the NativeProxy member. ** ptr: address of a void* that will receive the extract pointer. ** Returns: PR_SUCCESS for success, PR_FAILURE if an exception was thrown. ** ** Example: ** ** public class Owner { ** protected MyProxy myProxy; ** [...] ** } ** ** ** DataStructure *recovered; ** jobject owner; ** JNIEnv *env; ** [...] ** if(JSS_getPtrFromProxyOwner(env, owner, "myProxy", (void**)&recovered) ** != PR_SUCCESS) { ** return; // exception was thrown! ** } */ PRStatus JSS_getPtrFromProxyOwner(JNIEnv *env, jobject proxyOwner, char* proxyFieldName, char *proxyFieldSig, void **ptr) { jclass ownerClass; jfieldID proxyField; jobject proxyObject; PR_ASSERT(env!=NULL && proxyOwner!=NULL && proxyFieldName!=NULL && ptr!=NULL); /* * Get proxy object */ ownerClass = (*env)->GetObjectClass(env, proxyOwner); proxyField = (*env)->GetFieldID(env, ownerClass, proxyFieldName, proxyFieldSig); if(proxyField == NULL) { return PR_FAILURE; } proxyObject = (*env)->GetObjectField(env, proxyOwner, proxyField); if (proxyObject == NULL) { return PR_FAILURE; } /* * Get the pointer from the Native Reference object */ return JSS_getPtrFromProxy(env, proxyObject, ptr); } /*********************************************************************** ** ** J S S _ p t r T o B y t e A r r a y ** ** Turn a C pointer into a Java byte array. The byte array can be passed ** into a NativeProxy constructor. ** ** Returns a byte array containing the pointer, or NULL if an exception ** was thrown. */ jbyteArray JSS_ptrToByteArray(JNIEnv *env, void *ptr) { return JSS_ToByteArray(env, (void *)&ptr, sizeof(ptr)); } /*********************************************************************** * * J S S _ O c t e t S t r i n g T o B y t e A r r a y * * Converts a representation of an integer as a big-endian octet string * stored in a SECItem (as used by the low-level crypto functions) to a * representation of an integer as a big-endian Java byte array. Prepends * a zero byte to force it to be positive. Returns NULL if an exception * occurred. * */ jbyteArray JSS_OctetStringToByteArray(JNIEnv *env, SECItem *item) { jbyteArray array; jbyte *bytes; int size; /* size of the resulting byte array */ PR_ASSERT(env != NULL && item->len>0); /* allow space for extra zero byte */ size = item->len+1; array = (*env)->NewByteArray(env, size); if(array == NULL) { ASSERT_OUTOFMEM(env); return NULL; } bytes = (*env)->GetByteArrayElements(env, array, NULL); if(bytes == NULL) { ASSERT_OUTOFMEM(env); return NULL; } /* insert a 0 as the MSByte to force the string to be positive */ bytes[0] = 0; /* now insert the rest of the bytes */ memcpy(bytes+1, item->data, size-1); JSS_DerefByteArray(env, array, bytes, 0); return array; } #define ZERO_SECITEM(item) {(item).data=NULL; (item).len=0;} /*********************************************************************** * * J S S _ B y t e A r r a y T o O c t e t S t r i n g * * Converts an integer represented as a big-endian Java byte array to * an integer represented as a big-endian octet string in a SECItem. * * INPUTS * byteArray * A Java byte array containing an integer represented in * big-endian format. Must not be NULL. * item * Pointer to a SECItem that will be filled with the integer * from the byte array, in big-endian format. * RETURNS * PR_SUCCESS if the operation was successful, PR_FAILURE if an exception * was thrown. */ PRStatus JSS_ByteArrayToOctetString(JNIEnv *env, jbyteArray byteArray, SECItem *item) { jbyte *bytes=NULL; PRStatus status=PR_FAILURE; jsize size; PR_ASSERT(env!=NULL && byteArray!=NULL && item!=NULL); ZERO_SECITEM(*item); size = (*env)->GetArrayLength(env, byteArray); PR_ASSERT(size > 0); bytes = (*env)->GetByteArrayElements(env, byteArray, NULL); if(bytes==NULL) { ASSERT_OUTOFMEM(env); goto finish; } item->data = (unsigned char*) PR_Malloc(size); if(item->data == NULL) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } item->len = size; memcpy(item->data, bytes, size); status = PR_SUCCESS; finish: JSS_DerefByteArray(env, byteArray, bytes, JNI_ABORT); if(status != PR_SUCCESS) { SECITEM_FreeItem(item, PR_FALSE); } return status; } /************************************************************************ * * J S S _ w i p e C h a r A r r a y * * Given a string, set it to all zeroes. Be a chum and don't pass in NULL. */ void JSS_wipeCharArray(char* array) { PR_ASSERT(array != NULL); if(array == NULL) { return; } for(; *array != '\0'; array++) { *array = '\0'; } } #ifdef DEBUG static int debugLevel = JSS_TRACE_VERBOSE; #else static int debugLevel = JSS_TRACE_ERROR; #endif /********************************************************************** * * J S S _ t r a c e * * Sends a trace message. * * INPUTS * level * The trace level. * mesg * The trace message. Must not be NULL. */ void JSS_trace(JNIEnv *env, jint level, char *mesg) { PR_ASSERT(env!=NULL && mesg!=NULL); if(level <= debugLevel) { printf("%s\n", mesg); fflush(stdout); } } /*********************************************************************** * A S S E R T _ O U T O F M E M * * In most JNI calls that throw Exceptions, OutOfMemoryError is the only * one that doesn't indicate a bug in the code. If a JNI function throws * an exception (or returns an unexpected NULL), you can call this to * PR_ASSERT that it is due to an OutOfMemory condition. It takes a JNIEnv*, * which better not be NULL. */ void JSS_assertOutOfMem(JNIEnv *env) { jclass VARIABLE_MAY_NOT_BE_USED memErrClass; jthrowable excep; PR_ASSERT(env != NULL); /* Make sure an exception has been thrown, and save it */ excep = (*env)->ExceptionOccurred(env); PR_ASSERT(excep != NULL); /* Clear the exception so we can call JNI exceptions */ (*env)->ExceptionClear(env); /* See if the thrown exception was an OutOfMemoryError */ memErrClass = (*env)->FindClass(env, "java/lang/OutOfMemoryError"); PR_ASSERT(memErrClass != NULL); PR_ASSERT( (*env)->IsInstanceOf(env, excep, memErrClass) ); /* Re-throw the exception */ (*env)->Throw(env, excep); } /*********************************************************************** * Copies the contents of a SECItem into a new Java byte array. * * item * A SECItem. Must not be NULL. * RETURNS * A Java byte array. NULL will be returned if an exception was * thrown. */ jbyteArray JSS_SECItemToByteArray(JNIEnv *env, SECItem *item) { jbyteArray array=NULL; PR_ASSERT(env!=NULL && item!=NULL); PR_ASSERT(item->len == 0 || item->data != NULL); array = (*env)->NewByteArray(env, item->len); if( array == NULL ) { ASSERT_OUTOFMEM(env); goto finish; } (*env)->SetByteArrayRegion(env, array, 0, item->len, (jbyte*)item->data); finish: return array; } /*********************************************************************** * J S S _ B y t e A r r a y T o S E C I t e m * * Copies the contents of a Java byte array into a new SECItem. * * byteArray * A Java byte array. Must not be NULL. * RETURNS * A newly allocated SECItem, or NULL iff an exception was thrown. */ SECItem* JSS_ByteArrayToSECItem(JNIEnv *env, jbyteArray byteArray) { SECItem *item = NULL; PR_ASSERT(env!=NULL && byteArray!=NULL); /* Create a new SECItem */ item = PR_NEW(SECItem); if( item == NULL ) { JSS_throw(env, OUT_OF_MEMORY_ERROR); goto finish; } /* Setup the length, allocate the buffer */ item->len = (*env)->GetArrayLength(env, byteArray); item->data = PR_Malloc(item->len); /* copy the bytes from the byte array into the SECItem */ (*env)->GetByteArrayRegion(env, byteArray, 0, item->len, (jbyte*)item->data); if( (*env)->ExceptionOccurred(env) ) { SECITEM_FreeItem(item, PR_TRUE /*freeit*/); item = NULL; } finish: return item; } /************************************************************************ ** JSS_ToByteArray. ** ** Converts the given chararacter array to a Java byte array. ** ** Returns ** The new jbyteArray object or NULL on failure. */ jbyteArray JSS_ToByteArray(JNIEnv *env, const void *data, int length) { jbyteArray byteArray; byteArray = (*env)->NewByteArray(env, length); if (byteArray == NULL) { PR_ASSERT((*env)->ExceptionOccurred(env) != NULL); return NULL; } (*env)->SetByteArrayRegion(env, byteArray, 0, length, (jbyte *)data); if ((*env)->ExceptionOccurred(env) != NULL) { PR_ASSERT(PR_FALSE); return NULL; } return byteArray; } /************************************************************************ ** JSS_RefByteArray. ** ** References the contents of a Java ByteArray into *data, and optionally ** records length information to *lenght. Must be dereferenced via calling ** JSS_DerefByteArray. ** ** Returns ** bool - whether or not the operation succeeded. The operation succeeds ** if *data is successfully referenced (i.e., is non-null). */ bool JSS_RefByteArray(JNIEnv *env, jbyteArray array, jbyte **data, jsize *length) { bool ret = false; jsize array_length = 0; if (env == NULL || data == NULL) { goto done; } *data = NULL; if (array == NULL) { goto done; } array_length = (*env)->GetArrayLength(env, array); if (array_length <= 0) { goto done; } *data = (*env)->GetByteArrayElements(env, array, NULL); if (*data != NULL) { ret = true; } done: if (length != NULL) { *length = array_length; } return ret; } /************************************************************************ ** JSS_DerefByteArray. ** ** Dereferences the specified ByteArray and passed reference. mode is the ** same as given to (*env)->ReleaseByteArrayElements: 0 for copy and free, ** JNI_COMMIT for copy without freeing, and JNI_ABORT for free-only. ** */ void JSS_DerefByteArray(JNIEnv *env, jbyteArray array, void *data, jint mode) { if (env == NULL || array == NULL || data == NULL) { return; } (*env)->ReleaseByteArrayElements(env, array, (jbyte *) data, mode); } /************************************************************************ ** JSS_FromByteArray. ** ** Converts the given chararacter array from a Java byte array into a array of ** uint_t. When length is passed and is not NULL, *length is updated with the ** length of the byte array. The actual allocated size of *data is one more ** than *length to NULL terminate it. Note: *data must be freed with ** free(*data) after use, not with (*env)->ReleaseByteArrayElements. ** ** Returns ** bool - whether or not the operation succeeded. */ bool JSS_FromByteArray(JNIEnv *env, jbyteArray array, uint8_t **data, size_t *length) { jsize array_length = 0; jbyte *array_data = NULL; if (env == NULL || array == NULL || data == NULL) { return false; } *data = NULL; if (!JSS_RefByteArray(env, array, &array_data, &array_length)) { return false; } /* Defensive coding: Java's byte arrays are not null terminated, allocate * a structure one larger to guarantee C functions work as expected. */ *data = calloc(array_length + 1, sizeof(uint8_t)); memcpy(*data, array_data, array_length); // Copy length, if specified if (length != NULL) { *length = array_length; } // Give back our reference to array_data after destroying the contents. JSS_DerefByteArray(env, array, array_data, JNI_ABORT); return true; } /************************************************************************ ** JSS_RefJString ** ** Converts the given jstring object to a char *; must be freed with ** JSS_DerefJString(). ** ** Returns ** A reference to the characters underlying the given string. */ const char *JSS_RefJString(JNIEnv *env, jstring str) { const char *result = NULL; if (str == NULL) { return result; } /* Saving is_copy is useless in most cases: according to the Java * docs, we always have to call ReleaseStringUTFChars: * https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html */ result = (*env)->GetStringUTFChars(env, str, NULL); /* We've received a NULL result out of a non-NULL input string. This * means that the JNI code had an issue parsing the string as UTF8, so * raise an exception. */ if (result == NULL) { JSS_throwMsg(env, GENERAL_SECURITY_EXCEPTION, "Unable to parse Java String as UTF-8."); } return result; } /************************************************************************ ** JSS_DerefJString ** ** Returns the reference given by the JVM to a jstring's contents. ** */ void JSS_DerefJString(JNIEnv *env, jstring str, const char *ref) { if (str != NULL && ref != NULL) { (*env)->ReleaseStringUTFChars(env, str, ref); } } /************************************************************************ ** JSS_PK11_WrapCertToChain ** ** See jssutil.h for more information. ** */ jobjectArray JSS_PK11_WrapCertToChain(JNIEnv *env, CERTCertificate *cert, SECCertUsage certUsage) { CERTCertList *chain = CERT_GetCertChainFromCert(cert, PR_Now(), certUsage); // The only failure cases here are when we're out of memory; in which // case, there's not much more for us to do but return NULL. if (chain == NULL) { return NULL; } return JSS_PK11_wrapCertChain(env, &chain); } /************************************************************************ ** JSS_ExceptionToSECStatus ** ** When the JNI has thrown a known exception, convert this to a SECStatus ** code and set the appropriate PRErrorCode. ** ** See jssutil.h for a list of supported exceptions. ** */ SECStatus JSS_ExceptionToSECStatus(JNIEnv *env) { jclass clazz; jthrowable except = (*env)->ExceptionOccurred(env); if (except == NULL) { // No exception occurred; exit with success. PORT_SetError(0); return SECSuccess; } // Now we have to handle get the various cases. Each case involves looking // up a class by name and comparing it via IsInstanceOf(...). We ignore // failures which may occur on lookup. // CERTIFICATE_ENCODING_EXCEPTION <-> SEC_ERROR_CERT_NOT_VALID clazz = (*env)->FindClass(env, CERTIFICATE_ENCODING_EXCEPTION); if (clazz != NULL && (*env)->IsInstanceOf(env, except, clazz)) { PORT_SetError(SEC_ERROR_CERT_NOT_VALID); return SECFailure; } // CERTIFICATE_EXPIRED_EXCEPTION <-> SEC_ERROR_EXPIRED_CERTIFICATE clazz = (*env)->FindClass(env, CERTIFICATE_EXPIRED_EXCEPTION); if (clazz != NULL && (*env)->IsInstanceOf(env, except, clazz)) { PORT_SetError(SEC_ERROR_EXPIRED_CERTIFICATE); return SECFailure; } // CERTIFICATE_NOT_YET_VALID_EXCEPTION <-> SEC_ERROR_CERT_NOT_VALID clazz = (*env)->FindClass(env, CERTIFICATE_NOT_YET_VALID_EXCEPTION); if (clazz != NULL && (*env)->IsInstanceOf(env, except, clazz)) { PORT_SetError(SEC_ERROR_CERT_NOT_VALID); return SECFailure; } // CERTIFICATE_PARSING_EXCEPTION <-> SEC_ERROR_BAD_DER clazz = (*env)->FindClass(env, CERTIFICATE_PARSING_EXCEPTION); if (clazz != NULL && (*env)->IsInstanceOf(env, except, clazz)) { PORT_SetError(SEC_ERROR_BAD_DER); return SECFailure; } // CERTIFICATE_REVOKED_EXCEPTION <-> SEC_ERROR_REVOKED_CERTIFICATE clazz = (*env)->FindClass(env, CERTIFICATE_REVOKED_EXCEPTION); if (clazz != NULL && (*env)->IsInstanceOf(env, except, clazz)) { PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); return SECFailure; } // Handle the default case. Since these error messages are mostly // user-facing and don't get used internally, setting PR_UNKNOWN_ERROR // here is safe. PORT_SetError(PR_UNKNOWN_ERROR); return SECFailure; } /************************************************************************ ** JSS_SECStatusToException ** ** Convert a failing SECStatus and PRErrorCode combination into a raised ** JNI exception. ** ** See jssutil.h for a list of supported exceptions. ** */ void JSS_SECStatusToException(JNIEnv *env, SECStatus result, PRErrorCode code) { JSS_SECStatusToExceptionMessage(env, result, code, ""); } void JSS_SECStatusToExceptionMessage(JNIEnv *env, SECStatus result, PRErrorCode code, const char *message) { if (result == SECSuccess) { // We ignore PRErrorCode here. However, while we could clear an // exception if it occurred, we don't; that's the caller's choice to // make. return; } if (result == SECFailure) { switch (code) { case SEC_ERROR_CERT_NOT_VALID: JSS_throwMsgPrErrArg(env, CERTIFICATE_NOT_YET_VALID_EXCEPTION, message, code); break; case SEC_ERROR_EXPIRED_CERTIFICATE: JSS_throwMsgPrErrArg(env, CERTIFICATE_EXPIRED_EXCEPTION, message, code); break; case SEC_ERROR_BAD_DER: JSS_throwMsgPrErrArg(env, CERTIFICATE_PARSING_EXCEPTION, message, code); break; case SEC_ERROR_REVOKED_CERTIFICATE: JSS_throwMsgPrErrArg(env, CERTIFICATE_REVOKED_EXCEPTION, message, code); break; default: JSS_throwMsgPrErrArg(env, JAVA_LANG_EXCEPTION, message, code); break; } } } /*********************************************************************** ** ** JSS_clearPtrFromProxy ** ** See also: jssutil.h */ PRStatus JSS_clearPtrFromProxy(JNIEnv *env, jobject nativeProxy) { jclass proxyClass; jmethodID nativeProxyClear; PR_ASSERT(env!=NULL && nativeProxy != NULL); if( nativeProxy == NULL ) { JSS_throw(env, NULL_POINTER_EXCEPTION); return PR_FAILURE; } proxyClass = (*env)->GetObjectClass(env, nativeProxy); PR_ASSERT(proxyClass != NULL); nativeProxyClear = (*env)->GetMethodID(env, proxyClass, "clear", "()V"); if (nativeProxyClear == NULL) { ASSERT_OUTOFMEM(env); return PR_FAILURE; } (*env)->CallVoidMethod(env, nativeProxy, nativeProxyClear); if ((*env)->ExceptionOccurred(env)) { PR_ASSERT(PR_FALSE); return PR_FAILURE; } else { return PR_SUCCESS; } } /* V2 refers to PKCS #5 V2 here. If a PKCS #5 v1 or PKCS #12 pbe is passed * for pbeTag, then encTag and hashTag are ignored. If pbe is an encryption * algorithm, then PKCS #5 V2 is used with prfTag for the prf. If prfTag isn't * supplied prf will be SEC_OID_HMAC_SHA1 * JSS ported version of nss routine : PK11_ExportEncryptedPrivateKeyInfoV2 */ SECKEYEncryptedPrivateKeyInfo * JSS_ExportEncryptedPrivKeyInfoV2( PK11SlotInfo *slot, /* optional, encrypt key in this slot */ SECOidTag pbeAlg, /* PBE algorithm to encrypt the with key */ SECOidTag encAlg, /* Encryption algorithm to Encrypt the key with */ SECOidTag prfAlg, /* Hash algorithm for PRF */ SECItem *pwitem, /* password for PBE encryption */ SECKEYPrivateKey *pk, /* encrypt this private key */ int iteration, /* interations for PBE alg */ void *pwArg) /* context for password callback */ { SECKEYEncryptedPrivateKeyInfo *epki = NULL; PLArenaPool *arena = NULL; SECAlgorithmID *algid; SECOidTag pbeAlgTag = SEC_OID_UNKNOWN; SECItem *crypto_param = NULL; PK11SymKey *key = NULL; PK11SymKey *finalKey = NULL; SECStatus rv = SECSuccess; CK_RV crv; CK_ULONG encBufLen; CK_MECHANISM_TYPE pbeMechType; CK_MECHANISM_TYPE cryptoMechType; CK_MECHANISM cryptoMech; SECItem *iv = NULL; if (!pwitem || !pk) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return NULL; } algid = PK11_CreatePBEV2AlgorithmID(pbeAlg, encAlg, prfAlg, 0,iteration , NULL); if (algid == NULL) { return NULL; } arena = PORT_NewArena(2048); if (arena) epki = PORT_ArenaZNew(arena, SECKEYEncryptedPrivateKeyInfo); if (epki == NULL) { rv = SECFailure; goto loser; } epki->arena = arena; /* if we didn't specify a slot, use the slot the private key was in */ if (!slot) { slot = pk->pkcs11Slot; } /* if we specified a different slot, and the private key slot can do the * pbe key gen, generate the key in the private key slot so we don't have * to move it later */ pbeMechType = PK11_AlgtagToMechanism(pbeAlgTag); if (slot != pk->pkcs11Slot) { if (PK11_DoesMechanism(pk->pkcs11Slot, pbeMechType)) { slot = pk->pkcs11Slot; } } key = PK11_PBEKeyGen(slot, algid, pwitem, PR_FALSE, pwArg); if (key == NULL) { rv = SECFailure; goto loser; } cryptoMechType = PK11_GetPBECryptoMechanism(algid, &crypto_param, pwitem); if (cryptoMechType == CKM_INVALID_MECHANISM) { rv = SECFailure; goto loser; } cryptoMech.mechanism = PK11_GetPadMechanism(cryptoMechType); cryptoMech.pParameter = crypto_param ? crypto_param->data : NULL; cryptoMech.ulParameterLen = crypto_param ? crypto_param->len : 0; /* If the key isn't in the private key slot, move it */ if (PK11_GetSlotFromKey(key) != pk->pkcs11Slot) { PK11SymKey *newkey = PK11_MoveSymKey(pk->pkcs11Slot, CKA_WRAP, 0, PR_FALSE, key); /* We expect the PK11_MoveSymKey to fail in fips mode, * thus the need for further intervention with JSS_KeyExchange */ if (newkey == NULL) { /* couldn't import the wrapping key, try exchanging the * key */ CK_FLAGS opFlags = 0; opFlags |= CKF_UNWRAP; opFlags |= CKF_DECRYPT; opFlags |= CKF_ENCRYPT; newkey = JSS_KeyExchange(slot, cryptoMech.mechanism, CKA_WRAP,opFlags , PR_FALSE, key); if (newkey == NULL) { rv = SECFailure; goto loser; } finalKey = newkey; } else { /* free the old key and use the new key */ PK11_FreeSymKey(key); key = NULL; finalKey = newkey; } } else { finalKey = key; key = NULL; } /* we are extracting an encrypted privateKey structure. * which needs to be freed along with the buffer into which it is * returned. eventually, we should retrieve an encrypted key using * pkcs8/pkcs5. */ /* Allocate a large buffer to make sure we can fit the wrapped key */ encBufLen = 16384; epki->encryptedData.data = PORT_ArenaAlloc(arena, encBufLen); if (!epki->encryptedData.data) { rv = SECFailure; goto loser; } epki->encryptedData.len = (unsigned int)encBufLen; if (!epki->encryptedData.len) { rv = SECFailure; goto loser; } crv = PK11_WrapPrivKey(pk->pkcs11Slot, finalKey, pk, cryptoMechType, iv, &epki->encryptedData, NULL); /* crv = PK11_GETTAB(pk->pkcs11Slot)->C_WrapKey(pk->pkcs11Slot->session, &cryptoMech, key->objectID, pk->pkcs11ID, NULL, &encBufLen); */ if (crv != CKR_OK) { rv = SECFailure; goto loser; } rv = SECOID_CopyAlgorithmID(arena, &epki->algorithm, algid); loser: if (crypto_param != NULL) { SECITEM_ZfreeItem(crypto_param, PR_TRUE); crypto_param = NULL; } if (key != NULL) { PK11_FreeSymKey(key); } if (finalKey != NULL) { PK11_FreeSymKey(finalKey); } SECOID_DestroyAlgorithmID(algid, PR_TRUE); if (rv == SECFailure) { if (arena != NULL) { PORT_FreeArena(arena, PR_TRUE); } epki = NULL; } return epki; } /* Routine to exchange a key from one token to another, needed in extreme situations * where either we are in fips mode or a relectant hardware module won't allow the normal calls to work. * Based on original work from cipherboy aka ascheel. His code was based on the nss routine: pk11_KeyExchange * Note: the isPerm param is not yet observed since nss has no perm variant of PK11_PubUnwrapSymKeyWithMechanism. * In the future when this is true, we can change this to observe the perm flag which now is just treated as false. */ PK11SymKey * JSS_KeyExchange(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE operation, CK_FLAGS flags, PRBool isPerm, PK11SymKey *symKey) { int tempPrivKeyLength = 2048; PK11SymKey *newSymKey = NULL; SECStatus rv; PK11AttrFlags attrFlags = 0; /* performance improvement can go here --- use a generated key at startup * to generate a per token wrapping key. If it exists, use it, otherwise * do a full key exchange. */ /* find a common Key Exchange algorithm */ /* RSA */ int does_pkcs = PK11_DoesMechanism(PK11_GetSlotFromKey(symKey), CKM_RSA_PKCS) && \ PK11_DoesMechanism(slot, CKM_RSA_PKCS); int does_oaep = PK11_DoesMechanism(slot, CKM_RSA_PKCS_OAEP) && \ PK11_DoesMechanism(slot, CKM_RSA_PKCS_OAEP); if (does_pkcs || does_oaep) { SECKEYPublicKey *pubKey = NULL; SECKEYPrivateKey *privKey = NULL; SECItem wrapData; unsigned int symKeyLength = PK11_GetKeyLength(symKey); /* RSA-PKCS requires no parameters, but RSA-OAEP does. Construct with * sane defaults in case we end up needing to use them. */ CK_MECHANISM_TYPE our_mech = CKM_RSA_PKCS_OAEP; CK_RSA_PKCS_OAEP_PARAMS oaep_params = {CKM_SHA384, CKG_MGF1_SHA384, CKZ_DATA_SPECIFIED, NULL, 0}; SECItem oaep_param = {siBuffer, (unsigned char*)&oaep_params, sizeof(oaep_params)}; SECItem *mech_param = &oaep_param; if (!does_oaep) { /* Default to RSA OAEP. If the token does not do RSA OAEP, fall * back to RSA PKCS#1v1.5. */ our_mech = CKM_RSA_PKCS; mech_param = NULL; } wrapData.data = NULL; /* Just go ahead and generate a temp private key, * since this method is not going to be called often, * and we don't have to worry about finding a key with the * proper attributes.. */ PK11RSAGenParams rsaParams; rsaParams.keySizeInBits = tempPrivKeyLength; rsaParams.pe = 0x10001; attrFlags |= PK11_ATTR_SESSION; attrFlags |= PK11_ATTR_EXTRACTABLE; attrFlags |= (PK11_ATTR_SENSITIVE | PK11_ATTR_PRIVATE); privKey = PK11_GenerateKeyPairWithOpFlags(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, &rsaParams, &pubKey,attrFlags, flags,flags, NULL); if (privKey == NULL) goto rsa_failed; if (pubKey == NULL) goto rsa_failed; wrapData.len = SECKEY_PublicKeyStrength(pubKey); if (!wrapData.len) goto rsa_failed; wrapData.data = PORT_Alloc(wrapData.len); if (wrapData.data == NULL) goto rsa_failed; /* now wrap the keys in and out */ rv = PK11_PubWrapSymKeyWithMechanism(pubKey, our_mech, mech_param, symKey, &wrapData); if (rv == SECSuccess) { newSymKey = PK11_PubUnwrapSymKeyWithMechanism(privKey, our_mech, mech_param, &wrapData, type, operation, symKeyLength); /* make sure we wound up where we wanted to be! */ if (newSymKey && PK11_GetSlotFromKey(newSymKey) != slot) { PK11_FreeSymKey(newSymKey); newSymKey = NULL; } } rsa_failed: if (wrapData.data != NULL) PORT_Free(wrapData.data); if (privKey != NULL) SECKEY_DestroyPrivateKey(privKey); if (pubKey != NULL) SECKEY_DestroyPublicKey(pubKey); return newSymKey; } PORT_SetError(SEC_ERROR_NO_MODULE); return NULL; } /* * External references to the rcs and sccsc ident information in * jssver.c. These are here to prevent the compiler from optimizing * away the symbols in jssver.c */ extern const char __jss_base_rcsid[]; extern const char __jss_base_sccsid[]; jss-5.0.0/src/main/java/org/mozilla/jss/util/jssutil.h000066400000000000000000000321331412550063600226330ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include "pk11pub.h" #ifndef JSS_NATIVE_UTIL_H #define JSS_NATIVE_UTIL_H /* The following #defines are used to suppress undesired compiler warnings * that have been deemed inappropriate. * * IMPORTANT: These are ONLY used on an "as-needed" basis! */ #ifdef __GNUC__ #define FUNCTION_MAY_NOT_BE_USED __attribute__ ((unused)) #define VARIABLE_MAY_NOT_BE_USED __attribute__ ((unused)) #else #define FUNCTION_MAY_NOT_BE_USED #define VARIABLE_MAY_NOT_BE_USED #endif PR_BEGIN_EXTERN_C /**** NSPR private thread functions ****/ /* PRThread* PR_AttachThread(PRThreadType type, PRThreadPriority priority, PRThreadStack *stack); void PR_DetachThread(void); */ #define PR_AttachThread(a, b, c) ((PRThread*)1) #define PR_DetachThread() /* defined in CryptoManager.c */ extern JavaVM *JSS_javaVM; /*********************************************************************** * J S S _ t h r o w M s g * * Throw an exception in native code. You should return right after * calling this function. * * throwableClassName is the name of the throwable you are throwing in * JNI class name format (xxx/xx/xxx/xxx). It must not be NULL. * * message is the message parameter of the throwable. It must not be NULL. * If you don't have a message, call JSS_nativeThrow. * * Example: * JSS_nativeThrowMsg(env, "java/lang/IllegalArgumentException", * "Bogus argument, you ninny"); * return -1; */ void JSS_throwMsg(JNIEnv *env, const char *throwableClassName, const char *message); #define JSS_nativeThrowMsg JSS_throwMsg /*********************************************************************** * J S S _ t h r o w * * Throw an exception in native code. You should return right after * calling this function. * * throwableClassName is the name of the throwable you are throwing in * JNI class name format (xxx/xx/xxx/xxx). It must not be NULL. * * Example: * JSS_nativeThrow(env, "java/lang/IllegalArgumentException"); * return -1; */ void JSS_throw(JNIEnv *env, char *throwableClassName); #define JSS_nativeThrow JSS_throw /*********************************************************************** * A S S E R T _ O U T O F M E M * * In most JNI calls that throw Exceptions, OutOfMemoryError is the only * one that doesn't indicate a bug in the code. If a JNI function throws * an exception (or returns an unexpected NULL), you can call this to * PR_ASSERT that it is due to an OutOfMemory condition. It takes a JNIEnv*, * which better not be NULL. */ void JSS_assertOutOfMem(JNIEnv *env); #ifdef DEBUG #define ASSERT_OUTOFMEM(env) JSS_assertOutOfMem(env) #else #define ASSERT_OUTOFMEM(env) #endif /*********************************************************************** ** ** J S S _ g e t P t r F r o m P r o x y ** ** Given a NativeProxy, extract the pointer and store it at the given ** address. ** ** nativeProxy: a JNI reference to a NativeProxy. ** ptr: address of a void* that will receive the pointer extracted from ** the NativeProxy. ** Returns: PR_SUCCESS on success, PR_FAILURE if an exception was thrown. ** ** Example: ** DataStructure *recovered; ** jobject proxy; ** JNIEnv *env; ** [...] ** if(JSS_getPtrFromProxy(env, proxy, (void**)&recovered) != PR_SUCCESS) { ** return; // exception was thrown! ** } */ PRStatus JSS_getPtrFromProxy(JNIEnv *env, jobject nativeProxy, void **ptr); /*********************************************************************** ** ** J S S _ c l e a r P t r F r o m P r o x y ** ** Given a NativeProxy, clear the value of the pointer stored in it. This ** helps to ensure that a double free doesn't occur. ** ** Returns: PR_SUCCESS on success, PR_FAILURE if an exception was thrown. */ PRStatus JSS_clearPtrFromProxy(JNIEnv *env, jobject nativeProxy); /*********************************************************************** ** ** J S S _ g e t P t r F r o m P r o x y O w n e r ** ** Given an object which contains a NativeProxy, extract the pointer ** from the NativeProxy and store it at the given address. ** ** proxyOwner: an object which contains a NativeProxy member. ** proxyFieldName: the name of the NativeProxy member. ** proxyFieldSig: the signature of the NativeProxy member. ** ptr: address of a void* that will receive the extract pointer. ** Returns: PR_SUCCESS for success, PR_FAILURE if an exception was thrown. ** ** Example: ** ** public class Owner { ** protected MyProxy myProxy; ** [...] ** } ** ** ** DataStructure *recovered; ** jobject owner; ** JNIEnv *env; ** [...] ** if(JSS_getPtrFromProxyOwner(env, owner, "myProxy", (void**)&recovered) ** != PR_SUCCESS) { ** return; // exception was thrown! ** } */ PRStatus JSS_getPtrFromProxyOwner(JNIEnv *env, jobject proxyOwner, char* proxyFieldName, char *proxyFieldSig, void **ptr); /* * Turn a C pointer into a Java byte array. The byte array can be passed * into a NativeProxy constructor. * * Returns a byte array containing the pointer, or NULL if an exception * was thrown. */ jbyteArray JSS_ptrToByteArray(JNIEnv *env, void *ptr); /************************************************************************ * * J S S _ w i p e C h a r A r r a y * * Given a string, set it to all zeroes. Don't pass in NULL. */ void JSS_wipeCharArray(char* array); /********************************************************************** * * J S S _ t r a c e * * Sends a trace message. * * INPUTS * level * The trace level (see below for constants). Must be > 0. * mesg * The trace message. Must not be NULL. */ void JSS_trace(JNIEnv *env, jint level, char *mesg); /* trace levels */ #define JSS_TRACE_ERROR 1 #define JSS_TRACE_VERBOSE 5 #define JSS_TRACE_OBNOXIOUS 10 /*********************************************************************** * J S S _ S E C I t e m T o B y t e A r r a y * * Copies the contents of a SECItem into a new Java byte array. * * item * A SECItem. Must not be NULL. * RETURNS * A Java byte array. NULL will be returned if an exception was * thrown. */ jbyteArray JSS_SECItemToByteArray(JNIEnv *env, SECItem *item); /*********************************************************************** * J S S _ B y t e A r r a y T o S E C I t e m * * Copies the contents of a Java byte array into a new SECItem. * * byteArray * A Java byte array. Must not be NULL. * RETURNS * A newly allocated SECItem, or NULL iff an exception was thrown. */ SECItem* JSS_ByteArrayToSECItem(JNIEnv *env, jbyteArray byteArray); /*********************************************************************** * J S S _ s t r e r r o r * * Provides string representations for NSPR, SEC, and SSL errors. * Swiped from PSM. * * RETURNS * A UTF-8 encoded constant error string for errNum. * NULL if errNum is unknown. */ const char * JSS_strerror(PRErrorCode errNum); /*********************************************************************** ** ** J S S _ t h r o w M s g P r E r r A r g ** ** Throw an exception in native code. You should return right after ** calling this function. ** ** throwableClassName is the name of the throwable you are throwing in ** JNI class name format (xxx/xx/xxx/xxx). It must not be NULL. ** ** message is the message parameter of the throwable. It must not be NULL. ** If you don't have a message, call JSS_throw. ** ** errCode is a PRErrorCode returned from PR_GetError(). ** ** Example: ** JSS_throwMsg(env, ILLEGAL_ARGUMENT_EXCEPTION, PR_GetError()); ** return -1; */ void JSS_throwMsgPrErrArg(JNIEnv *env, const char *throwableClassName, const char *message, PRErrorCode errCode); #define JSS_throwMsgPrErr(e, cn, m) \ JSS_throwMsgPrErrArg((e), (cn), (m), PR_GetError()) #define JSS_throwMsgPortErr(e, cn, m) \ JSS_throwMsgPrErrArg((e), (cn), (m), PORT_GetError()) /************************************************************************ ** ** J S S _ i n i t E r r c o d e T r a n s l a t i o n T a b l e. ** ** Initializes the error code translation table. This should be called ** by CryptoManager.initialize(), and must be called before any calls to ** JSS_ConvertNativeErrcodeToJava. ** */ void JSS_initErrcodeTranslationTable(); /************************************************************************ ** ** J S S _ C o n v e r t N a t i v e E r r c o d e T o J a v a ** ** Converts an NSPR or NSS error code to a Java error code. ** (defined in the class o.m.util.NativeErrcodes) ** ** Returns ** The Java error code, or -1 if a corresponding Java error code could ** not be found. */ int JSS_ConvertNativeErrcodeToJava(int nativeErrcode); /************************************************************************ ** JSS_ToByteArray. ** ** Converts the given chararacter array to a Java byte array. ** ** Returns ** The new jbyteArray object or NULL on failure. */ jbyteArray JSS_ToByteArray(JNIEnv *env, const void *data, int length); /************************************************************************ ** JSS_RefByteArray. ** ** References the contents of a Java ByteArray into *data, and optionally ** records length information to *lenght. Must be dereferenced via calling ** JSS_DerefByteArray. ** ** Returns ** bool - whether or not the operation succeeded. */ bool JSS_RefByteArray(JNIEnv *env, jbyteArray array, jbyte **data, jsize *length); /************************************************************************ ** JSS_DerefByteArray. ** ** Dereferences the specified ByteArray and passed reference. mode is the ** same as given to (*env)->ReleaseByteArrayElements: 0 for copy and free, ** JNI_COMMIT for copy without freeing, and JNI_ABORT for free-only. ** */ void JSS_DerefByteArray(JNIEnv *env, jbyteArray array, void *data, jint mode); /************************************************************************ ** JSS_FromByteArray. ** ** Converts the given chararacter array from a Java byte array into a array of ** uint_t. When length is passed and is not NULL, *length is updated with the ** length of the array. ** ** Returns ** bool - whether or not the operation succeeded. */ bool JSS_FromByteArray(JNIEnv *env, jbyteArray array, uint8_t **data, size_t *length); /************************************************************************ ** JSS_RefJString ** ** Converts the given jstring object to a char *; must be freed with ** JSS_DerefJString(). ** ** Returns ** A reference to the characters underlying the given string. */ const char *JSS_RefJString(JNIEnv *env, jstring str); /************************************************************************ ** JSS_DerefJString ** ** Returns the reference given by the JVM to a jstring's contents. ** */ void JSS_DerefJString(JNIEnv *env, jstring str, const char *ref); /************************************************************************ ** JSS_PK11_WrapCertToChain ** ** Inquires about the certificate chain for cert, and returns the full or ** partial as a jobjectArray for use in JNI'd code. ** */ jobjectArray JSS_PK11_WrapCertToChain(JNIEnv *env, CERTCertificate *cert, SECCertUsage certUsage); /************************************************************************ ** JSS_ExceptionToSECStatus ** ** When the JNI has thrown a known exception, convert this to a SECStatus ** code and set the appropriate PRErrorCode. ** ** The supported exceptions are: ** - CertificateException ** */ SECStatus JSS_ExceptionToSECStatus(JNIEnv *env); /************************************************************************ ** JSS_SECStatusToException ** ** Convert a failing SECStatus and PRErrorCode combination into a raised ** JNI exception. ** ** The supported exceptions are: ** - CertificateException ** */ void JSS_SECStatusToException(JNIEnv *env, SECStatus result, PRErrorCode code); /************************************************************************ ** JSS_SECStatusToException ** ** Convert a failing SECStatus and PRErrorCode combination into a raised ** JNI exception with the specified message. ** ** The supported exceptions are: ** - CertificateException ** */ void JSS_SECStatusToExceptionMessage(JNIEnv *env, SECStatus result, PRErrorCode code, const char *message); SECKEYEncryptedPrivateKeyInfo * JSS_ExportEncryptedPrivKeyInfoV2( PK11SlotInfo *slot, /* optional, encrypt key in this slot */ SECOidTag pbeAlg, /* PBE algorithm to encrypt the with key */ SECOidTag encAlg, /* Encryption algorithm to Encrypt the key with */ SECOidTag prfAlg, /* Hash algorithm for PRF */ SECItem *pwitem, /* password for PBE encryption */ SECKEYPrivateKey *pk, /* encrypt this private key */ int iteration, /* interations for PBE alg */ void *pwArg); PK11SymKey * JSS_KeyExchange(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE operation, CK_FLAGS flags, PRBool isPerm, PK11SymKey *symKey); PR_END_EXTERN_C #endif jss-5.0.0/src/main/java/org/mozilla/jss/util/jssver.c000066400000000000000000000014031412550063600224410ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "jssver.h" /* Library identity and versioning */ #if defined(DEBUG) #define _DEBUG_STRING " (debug)" #else #define _DEBUG_STRING "" #endif /* * Version information for the 'ident' and 'what commands * * NOTE: the first component of the concatenated rcsid string * must not end in a '$' to prevent rcs keyword substitution. */ const char __jss_base_rcsid[] = "$Header: JSS " JSS_VERSION _DEBUG_STRING " " __DATE__ " " __TIME__ " $"; const char __jss_base_sccsid[] = "@(#)JSS " JSS_VERSION _DEBUG_STRING " " __DATE__ " " __TIME__; jss-5.0.0/src/main/java/org/mozilla/jss/util/jssver.h.in000066400000000000000000000020001412550063600230450ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef JSSVER_H #define JSSVER_H /* * JSS's major version, minor version, patch level, and whether * this is a beta release. * * The format of the version string should be * ".[.] []" */ /********************************************************************/ /* The VERSION Strings should be updated everytime a new release */ /* of JSS is generated. Note that this is done by changing */ /* cmake/JSSConfig.cmake. */ /********************************************************************/ #define JSS_VERSION "${JSS_VERSION}" #define JSS_VMAJOR ${JSS_VERSION_MAJOR} #define JSS_VMINOR ${JSS_VERSION_MINOR} #define JSS_VPATCH ${JSS_VERSION_PATCH} #define JSS_BETA ${JSS_VERSION_BETA} #endif jss-5.0.0/src/test/000077500000000000000000000000001412550063600140635ustar00rootroot00000000000000jss-5.0.0/src/test/java/000077500000000000000000000000001412550063600150045ustar00rootroot00000000000000jss-5.0.0/src/test/java/org/000077500000000000000000000000001412550063600155735ustar00rootroot00000000000000jss-5.0.0/src/test/java/org/mozilla/000077500000000000000000000000001412550063600172425ustar00rootroot00000000000000jss-5.0.0/src/test/java/org/mozilla/jss/000077500000000000000000000000001412550063600200415ustar00rootroot00000000000000jss-5.0.0/src/test/java/org/mozilla/jss/tests/000077500000000000000000000000001412550063600212035ustar00rootroot00000000000000jss-5.0.0/src/test/java/org/mozilla/jss/tests/BMPStringTest.java000066400000000000000000000215551412550063600245230ustar00rootroot00000000000000package org.mozilla.jss.tests; import org.junit.Assert; import org.junit.Test; import org.mozilla.jss.netscape.security.util.DerValue; public class BMPStringTest { public byte tag = DerValue.tag_BMPString; @Test public void testEncodingEmptyString() throws Exception { String string = ""; System.out.println("Encoding: [" + string + "]"); byte[] expected = JSSUtil.encode(tag, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testDecodingEmptyString() throws Exception { String input = ""; byte[] data = JSSUtil.encode(tag, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: [" + input + "]"); String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + output + "]"); Assert.assertEquals(input, output); } @Test public void testEncodingNullCharacters() throws Exception { String string = StringTestUtil.NULL_CHARS; System.out.println("Encoding: [" + StringTestUtil.toString(string.getBytes()) + "]"); byte[] expected = JSSUtil.encode(tag, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); actual = StringTestUtil.normalizeUnicode(actual); System.out.println(" - norm. : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testDecodingNullCharacters() throws Exception { String input = StringTestUtil.NULL_CHARS; byte[] data = JSSUtil.encode(tag, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: [" + StringTestUtil.toString(input.getBytes()) + "]"); String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + StringTestUtil.toString(output.getBytes()) + "]"); Assert.assertEquals(input, output); } @Test public void testEncodingPrintableCharacters() throws Exception { String string = StringTestUtil.PRINTABLE_CHARS; System.out.println("Encoding: [" + string + "]"); byte[] expected = JSSUtil.encode(tag, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); actual = StringTestUtil.normalizeUnicode(actual); System.out.println(" - norm. : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testDecodingPrintableCharacters() throws Exception { String input = StringTestUtil.PRINTABLE_CHARS; byte[] data = JSSUtil.encode(tag, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: [" + input + "]"); String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + output + "]"); Assert.assertEquals(input, output); } @Test public void testEncodingNonPrintableCharacters() throws Exception { String string = StringTestUtil.NON_PRINTABLE_CHARS; System.out.println("Encoding: [" + string + "]"); byte[] expected = JSSUtil.encode(tag, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); actual = StringTestUtil.normalizeUnicode(actual); System.out.println(" - norm. : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testDecodingNonPrintableCharacters() throws Exception { String input = StringTestUtil.NON_PRINTABLE_CHARS; byte[] data = JSSUtil.encode(tag, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: [" + input + "]"); String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + output + "]"); Assert.assertEquals(input, output); } @Test public void testEncodingControlCharacters() throws Exception { String string = StringTestUtil.CONTROL_CHARS; System.out.println("Encoding: [" + StringTestUtil.toString(string.getBytes()) + "]"); byte[] expected = JSSUtil.encode(tag, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); actual = StringTestUtil.normalizeUnicode(actual); System.out.println(" - norm. : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testDecodingControlCharacters() throws Exception { String input = StringTestUtil.CONTROL_CHARS; byte[] data = JSSUtil.encode(tag, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: [" + StringTestUtil.toString(input.getBytes()) + "]"); String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + StringTestUtil.toString(output.getBytes()) + "]"); Assert.assertEquals(input, output); } @Test public void testEncodingMultibyteCharacters() throws Exception { String string = StringTestUtil.MULTIBYTE_CHARS; System.out.println("Encoding: [" + string + "]"); byte[] expected = JSSUtil.encode(tag, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); actual = StringTestUtil.normalizeUnicode(actual); System.out.println(" - norm. : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testDecodingMultibyteCharacters() throws Exception { String input = StringTestUtil.MULTIBYTE_CHARS; byte[] data = JSSUtil.encode(tag, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: [" + StringTestUtil.toString(input.getBytes()) + "]"); String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + StringTestUtil.toString(output.getBytes()) + "]"); Assert.assertEquals(input, output); } @Test public void testEncodingTime() throws Exception { System.out.println("Encoding time:"); String string = StringTestUtil.NULL_CHARS + StringTestUtil.PRINTABLE_CHARS + StringTestUtil.NON_PRINTABLE_CHARS + StringTestUtil.CONTROL_CHARS + StringTestUtil.MULTIBYTE_CHARS; long t0 = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) JSSUtil.encode(tag, string); long t1 = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) StringTestUtil.encode(tag, string); long t2 = System.currentTimeMillis(); long time1 = t1 - t0; long time2 = t2 - t1; System.out.println(" - JSS : " + time1 + " ms"); System.out.println(" - Internal: " + time2 + " ms"); } @Test public void testDecodingTime() throws Exception { System.out.println("Decoding time:"); String string = StringTestUtil.NULL_CHARS + StringTestUtil.PRINTABLE_CHARS + StringTestUtil.NON_PRINTABLE_CHARS + StringTestUtil.CONTROL_CHARS + StringTestUtil.MULTIBYTE_CHARS; byte[] data = JSSUtil.encode(tag, string); long t0 = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) JSSUtil.decode(tag, data); long t1 = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) StringTestUtil.decode(tag, data); long t2 = System.currentTimeMillis(); long time1 = t1 - t0; long time2 = t2 - t1; System.out.println(" - JSS : " + time1 + " ms"); System.out.println(" - Internal: " + time2 + " ms"); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/BadSSL.java000066400000000000000000000210331412550063600231150ustar00rootroot00000000000000package org.mozilla.jss.tests; import java.io.IOException; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.TrustManager; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.provider.javax.crypto.JSSNativeTrustManager; import org.mozilla.jss.ssl.javax.JSSSocket; import org.mozilla.jss.ssl.javax.JSSSocketFactory; /** * The BadSSL test case maintains an internal mapping from badssl.com * subdomains to expected exceptions and validates they occur. * * Since badssl.com offers no guaranteed SLA or availability, we likely * shouldn't add this site to automated tests. */ public class BadSSL { private static javax.net.ssl.SSLContext ctx; private static JSSSocketFactory jsf; public static KeyManager[] getKMs() throws Exception { KeyManagerFactory kmf = KeyManagerFactory.getInstance("NssX509"); return kmf.getKeyManagers(); } public static void main(String[] args) throws Exception { boolean ocsp = false; if (args.length < 1) { System.out.println("Usage: BadSSL nssdb [LEAF_AND_CHAIN]"); return; } if (args.length >= 2 && args[1].equals("LEAF_AND_CHAIN")) { System.out.println("Enabling leaf and chain policy..."); ocsp = true; } CryptoManager cm = CryptoManager.getInstance(); if (ocsp) { CryptoManager.setOCSPPolicy(CryptoManager.OCSPPolicy.LEAF_AND_CHAIN); } ctx = javax.net.ssl.SSLContext.getInstance("TLS", "Mozilla-JSS"); ctx.init(getKMs(), new TrustManager[] { new JSSNativeTrustManager() }, null); jsf = (JSSSocketFactory) ctx.getSocketFactory(); // Test cases which should fail due to various certificate errors. testExpired(); testWrongHost(); testSelfSigned(); testUntrustedRoot(); // The following test cases depend on crypto-policies or local NSS // configuration. testSHA1(); testRC4MD5(); testRC4(); test3DES(); testNULL(); // The following test cases depend on OCSP being enabled. if (ocsp) { testRevoked(); } // Test cases which should pass given the correct root certs. testSHA256(); testSHA384(); testSHA512(); testECC256(); testECC384(); testRSA2048(); testRSA4096(); testRSA8192(); testExtendedValidation(); } /* Test cases whose handshakes should fail below. */ public static void testExpired() throws Exception { testHelper("expired.badssl.com", 443, new String[]{ "(-8181)", "has expired" }); } public static void testWrongHost() throws Exception { testHelper("wrong.host.badssl.com", 443, new String[]{ "(-12276)", "domain name does not match" }); } public static void testSelfSigned() throws Exception { testHelper("self-signed.badssl.com", 443, new String[]{ "(-8101)", "(-8156)", "type not approved", "issuer certificate is invalid" }); } public static void testUntrustedRoot() throws Exception { testHelper("untrusted-root.badssl.com", 443, new String[]{ "(-8172)", "certificate issuer has been marked as not trusted" }); } public static void testRevoked() throws Exception { testHelper("revoked.badssl.com", 443, new String[]{ "(-8180)", "has been revoked" }); } public static void testSHA1() throws Exception { try { testHelper("sha1-intermediate.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" }); } catch (Exception e) { } } public static void testRC4MD5() throws Exception { try { testHelper("rc4-md5.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" }); } catch (Exception e) { } } public static void testRC4() throws Exception { try { testHelper("rc4.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" }); } catch (Exception e) { } } public static void test3DES() throws Exception { try { testHelper("3des.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" }); } catch (Exception e) { } } public static void testNULL() throws Exception { try { testHelper("null.badssl.com", 443, new String[] { "(-12286)", "Cannot communicate securely" }); } catch (Exception e) { } } /* Test cases which should handshake successfully below. */ public static void testSHA256() throws Exception { testHelper("sha256.badssl.com", 443); } public static void testSHA384() throws Exception { testHelper("sha384.badssl.com", 443); } public static void testSHA512() throws Exception { testHelper("sha512.badssl.com", 443); } public static void testECC256() throws Exception { testHelper("ecc256.badssl.com", 443); } public static void testECC384() throws Exception { testHelper("ecc384.badssl.com", 443); } public static void testRSA2048() throws Exception { testHelper("rsa2048.badssl.com", 443); } public static void testRSA4096() throws Exception { testHelper("rsa4096.badssl.com", 443); } public static void testRSA8192() throws Exception { testHelper("rsa8192.badssl.com", 443); } public static void testExtendedValidation() throws Exception { testHelper("extended-validation.badssl.com", 443); } /* Test case helpers. */ public static void testHelper(String host, int port) throws Exception { testSiteOldSSLSocket(host, port); testSiteJavaxSSLSocket(host, port); System.out.println("\t...ok"); } public static void testHelper(String host, int port, String[] substrs) throws Exception { testHelperOld(host, port, substrs); testHelperJavax(host, port, substrs); } public static void testHelperOld(String host, int port, String[] substrs) throws Exception { try { testSiteOldSSLSocket(host, port); } catch (org.mozilla.jss.ssl.SSLSocketException sse) { String actual = sse.getMessage().toLowerCase(); for (String expected : substrs) { if (actual.contains(expected.toLowerCase())) { System.out.println("\t...got expected error message."); return; } } if (actual.contains("(-8016) unknown error")) { System.out.println("\t...got unknown error; continuing anyways."); return; } System.err.println("\tUnexpected error message: " + actual); throw sse; } throw new RuntimeException("Expected to get an exception, but didn't!"); } public static void testHelperJavax(String host, int port, String[] substrs) throws Exception { try { testSiteJavaxSSLSocket(host, port); } catch (IOException sse) { String actual = sse.getMessage().toLowerCase(); for (String expected : substrs) { if (actual.contains(expected.toLowerCase())) { System.out.println("\t...got expected error message."); return; } } if (actual.contains("(-8016) unknown error")) { System.out.println("\t...got unknown error; continuing anyways."); return; } System.err.println("\tUnexpected error message: " + actual); throw sse; } throw new RuntimeException("Expected to get an exception, but didn't!"); } public static void testSiteOldSSLSocket(String host, int port) throws Exception { System.out.println("Testing connection to " + host + ":" + port); try (org.mozilla.jss.ssl.SSLSocket sock = new org.mozilla.jss.ssl.SSLSocket(host, 443)) { sock.forceHandshake(); sock.shutdownOutput(); sock.shutdownInput(); } } public static void testSiteJavaxSSLSocket(String host, int port) throws Exception { System.out.println("Testing connection to " + host + ":" + port); try (JSSSocket sock = jsf.createSocket(host, port)) { sock.setUseClientMode(true); sock.setWantClientAuth(false); sock.setNeedClientAuth(false); sock.setHostname(host); sock.startHandshake(); sock.shutdownOutput(); sock.shutdownInput(); } } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/Base64Parsing.java000066400000000000000000000043411412550063600244200ustar00rootroot00000000000000package org.mozilla.jss.tests; import java.util.Arrays; import org.mozilla.jss.netscape.security.util.Utils; public class Base64Parsing { public static String mime = "MIICjDCCAXQCAQIwADCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALdt\nHPsAesaTlWRE3pyW6PtDhbQSUt/jYbKSxLMR7uln7YNiL74pYHFNZ9ZrW51GWPF0\nKqldtx6c3zAweynehJtI/AR5pDtHi8bh8L8mqLpsJXgSx5laAGt2n/aAXNxJNS85\n4b/q6lV7k6nIfECsZwTkQV3LCEISjbW9jNLQsuSAV/TznJ3UoEmZh9YMA+cwpBBo\nnLcHxRx+0ymq9R53yUCyAUfLWl0pbfUlCF0EKHJ25et/T8TftzMqdLFJ23gyONdj\nzgPhc0fNN4fKYqvisg/9V+v0NaVR8VtV1yOhRZp4qy+7JCC6veCb1BZtAVfYJYA4\nMj+k9Una6z6Qnjl97VECAwEAAaBHMEUGCSqGSIb3DQEJDjE4MDYwNAYDVR0RBC0w\nK4Ipdm0tMTcxLTEyNC5hYmMuaWRtLmxhYi5lbmcuYnJxLnJlZGhhdC5jb20wDQYJ\nKoZIhvcNAQELBQADggEBAImj0y3AaGwCxlkgkGtlou4eookqD/xnaeckmS3cil5M\nA6Ff1Ec0orcYBTNBIGwjQN7Z7FC/7ALOa4E94AfqFl6kquy4ArxrVsP3OIC5kGE6\nkLcz6F2MJCRuNQdGdxBujlCYyjv4Wr67rLgzeSUD+DGPMehFvdQxTW8VorKBaIxx\ntFtqiFZtEs/9bSVfw0jzC4a5maM77kl819I9TXNwwEjGd3/eNmab42qvp9KvXS6Y\nhTD+sqE5GmL09YvV3KR1vU1o+9iGJF9Nvg8xOROzTCN+U+TKLv982kbOrrKYwdgn\nfYlMwsGlnPuwSNhMH51fxZU5o/F6EXOAdLqIEPEuFQo=\n"; public static String url_safe = "MIICjDCCAXQCAQIwADCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALdtHPsAesaTlWRE3pyW6PtDhbQSUt_jYbKSxLMR7uln7YNiL74pYHFNZ9ZrW51GWPF0Kqldtx6c3zAweynehJtI_AR5pDtHi8bh8L8mqLpsJXgSx5laAGt2n_aAXNxJNS854b_q6lV7k6nIfECsZwTkQV3LCEISjbW9jNLQsuSAV_TznJ3UoEmZh9YMA-cwpBBonLcHxRx-0ymq9R53yUCyAUfLWl0pbfUlCF0EKHJ25et_T8TftzMqdLFJ23gyONdjzgPhc0fNN4fKYqvisg_9V-v0NaVR8VtV1yOhRZp4qy-7JCC6veCb1BZtAVfYJYA4Mj-k9Una6z6Qnjl97VECAwEAAaBHMEUGCSqGSIb3DQEJDjE4MDYwNAYDVR0RBC0wK4Ipdm0tMTcxLTEyNC5hYmMuaWRtLmxhYi5lbmcuYnJxLnJlZGhhdC5jb20wDQYJKoZIhvcNAQELBQADggEBAImj0y3AaGwCxlkgkGtlou4eookqD_xnaeckmS3cil5MA6Ff1Ec0orcYBTNBIGwjQN7Z7FC_7ALOa4E94AfqFl6kquy4ArxrVsP3OIC5kGE6kLcz6F2MJCRuNQdGdxBujlCYyjv4Wr67rLgzeSUD-DGPMehFvdQxTW8VorKBaIxxtFtqiFZtEs_9bSVfw0jzC4a5maM77kl819I9TXNwwEjGd3_eNmab42qvp9KvXS6YhTD-sqE5GmL09YvV3KR1vU1o-9iGJF9Nvg8xOROzTCN-U-TKLv982kbOrrKYwdgnfYlMwsGlnPuwSNhMH51fxZU5o_F6EXOAdLqIEPEuFQo"; public static void main(String[] args) throws Exception { byte[] mime_data = Utils.base64decode(mime); assert(mime_data.length == 656); byte[] url_data = Utils.base64decode(url_safe); assert(url_data.length == 656); assert(Arrays.equals(mime_data, url_data)); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/BenchmarkSSLSocket.java000066400000000000000000000240701412550063600254760ustar00rootroot00000000000000package org.mozilla.jss.tests; import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.security.KeyStore; import java.util.ArrayList; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLServerSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import org.mozilla.jss.provider.javax.crypto.JSSNativeTrustManager; /** * Utility for benchmarking the performance of SSLSocket implementations. * * For information about using this benchmark, see the documentation in this * repo at: /docs/usage/benchmarksslsocket.md */ public class BenchmarkSSLSocket { public String type; public String nickname; public String password; public int port; public int size; public String headers = "HTTP/1.1 200 OK\r\nConnection: Closed\r\n"; public String message; public int limit = 150; public BenchmarkSSLSocket(String type, String nickname, int port, int size) throws Exception { this.type = type; this.nickname = nickname; this.port = port; this.size = size; this.limit = limit; headers = headers + "Content-Length: " + size + "\r\n"; StringBuilder sb = new StringBuilder(size); for (int i = 0; i < size; i++) { sb.append("a"); } message = headers + "\r\n" + sb.toString(); } public BenchmarkSSLSocket(String type, String nickname, String password, int port, int size) throws Exception { this(type, nickname, port, size); this.password = password; } public ServerSocket getServerSocket() throws Exception { System.err.println("Constructing socket..."); switch (type) { case "JSS.legacy": { org.mozilla.jss.ssl.SSLServerSocket sock = new org.mozilla.jss.ssl.SSLServerSocket(port); sock.setSoTimeout(0); org.mozilla.jss.ssl.SSLServerSocket.configServerSessionIDCache(0, 43200, 43200, null); sock.setReuseAddress(true); sock.requestClientAuth(false); sock.requireClientAuth(org.mozilla.jss.ssl.SSLSocket.SSL_REQUIRE_NEVER); sock.setUseClientMode(false); sock.setServerCertNickname(nickname); return sock; } case "JSS.SSLSocket": { KeyManagerFactory kmf = KeyManagerFactory.getInstance("NssX509"); SSLContext ctx = SSLContext.getInstance("TLS", "Mozilla-JSS"); ctx.init( kmf.getKeyManagers(), new TrustManager[] { new JSSNativeTrustManager() }, null ); SSLServerSocketFactory factory = ctx.getServerSocketFactory(); org.mozilla.jss.ssl.javax.JSSServerSocket sock = (org.mozilla.jss.ssl.javax.JSSServerSocket) factory.createServerSocket(port); sock.setReuseAddress(true); sock.setWantClientAuth(false); sock.setNeedClientAuth(false); sock.setUseClientMode(false); sock.setCertFromAlias(nickname); return sock; } case "SunJSSE.SSLSocket": { FileInputStream fis = new FileInputStream(nickname); KeyStore store = KeyStore.getInstance("PKCS12"); store.load(fis, "m1oZilla".toCharArray()); // Courtesy of https://stackoverflow.com/questions/537040/how-to-connect-to-a-secure-website-using-ssl-in-java-with-a-pkcs12-file // Without using a JKS-type KeyStore for the TrustManager, // constructing a TrustManagerFactory will consume 100% CPU // and we won't reach the SSLServerSocketFactory code. KeyStore jks = KeyStore.getInstance("JKS"); jks.load(null); KeyStore ks = store; for (java.util.Enumeration t = ks.aliases(); t.hasMoreElements(); ) { String alias = t.nextElement(); if (ks.isKeyEntry(alias)) { java.security.cert.Certificate[] a = ks.getCertificateChain(alias); // i = 1 skips the CA certificate for (int i = 1; i < a.length; i++) { java.security.cert.X509Certificate x509 = (java.security.cert.X509Certificate) a[i]; jks.setCertificateEntry(x509.getSubjectDN().toString(), x509); } } } KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(store, "m1oZilla".toCharArray()); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(jks); SSLContext ctx = SSLContext.getInstance("TLS", "SunJSSE"); ctx.init( kmf.getKeyManagers(), tmf.getTrustManagers(), null ); SSLServerSocketFactory factory = ctx.getServerSocketFactory(); javax.net.ssl.SSLServerSocket sock = (javax.net.ssl.SSLServerSocket) factory.createServerSocket(port); sock.setReuseAddress(true); sock.setWantClientAuth(false); sock.setNeedClientAuth(false); sock.setUseClientMode(false); return sock; } default: throw new RuntimeException("Unknown socket type: `" + type + "` -- expected one of `JSS.SSLSocket`, `JSS.legacy`, or `SunJSSE.SSLSocket`."); } } class PeerTask implements Runnable { Socket peer; byte[] message; public PeerTask(Socket peer, String message) { this.peer = peer; this.message = message.getBytes(); } @Override public void run() { try { try { // First, force a handshake if (peer instanceof org.mozilla.jss.ssl.SSLSocket) { org.mozilla.jss.ssl.SSLSocket sock = (org.mozilla.jss.ssl.SSLSocket) peer; sock.setUseClientMode(false); sock.forceHandshake(); } else if (peer instanceof javax.net.ssl.SSLSocket) { javax.net.ssl.SSLSocket sock = (javax.net.ssl.SSLSocket) peer; sock.setUseClientMode(false); sock.startHandshake(); } // Consume all input data. InputStream is = peer.getInputStream(); byte[] in_data = new byte[is.available()]; is.read(in_data); // Send our message back. OutputStream os = peer.getOutputStream(); os.write(message); } finally { peer.close(); } } catch (Exception e) { throw new RuntimeException(e.getMessage(), e); } } } public void run() throws Exception { ArrayList existing = new ArrayList(limit); try ( ServerSocket server_socket = getServerSocket(); ) { System.err.println("Listening for connections..."); while (true) { int length = existing.size(); while (length > limit) { int index = 0; while (index < length) { Thread.sleep(10); if (existing.get(index).isAlive()) { index += 1; } else { existing.remove(index); length -= 1; } } } Socket peer_socket = server_socket.accept(); Runnable task = new PeerTask(peer_socket, message); Thread thread = new Thread(task); thread.start(); } } } public static void main(String[] args) throws Exception { if (args.length < 4 || args.length > 5) { System.err.println("Usage: BenchmarkSSLSocket [...args...]"); System.err.println("type: JSS.SSLSocket, JSS.legacy, or SunJSSE.SSLSocket\n"); System.err.println("When type is JSS.SSLSocket or JSS.legacy:"); System.err.println("Usage: BenchmarkSSLSocket "); System.err.println("alias: server certificate nickname"); System.err.println("port: What server port to listen on"); System.err.println("size: bytes of body to send in reply (plus header size)\n"); System.err.println("When type is SunJSSE.SSLSocket:"); System.err.println("Usage: BenchmarkSSLSocket SunJSSE.SSLSocket [] "); System.err.println("p12path: path to the p12 file containing the server cert"); System.err.println("p12pass: password to access p12 file with; default: m1oZilla"); System.err.println("port: What server port to listen on"); System.err.println("size: bytes of body to send in reply (plus header size)\n"); System.exit(1); } BenchmarkSSLSocket benchmark; if (args.length == 4) { String type = args[0]; String alias = args[1]; int port = Integer.parseInt(args[2]); int size = Integer.parseInt(args[3]); benchmark = new BenchmarkSSLSocket(type, alias, "m1oZilla", port, size); } else { String type = args[0]; String path = args[1]; String password = args[2]; int port = Integer.parseInt(args[3]); int size = Integer.parseInt(args[4]); benchmark = new BenchmarkSSLSocket(type, path, password, port, size); } benchmark.run(); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/BigObjectIdentifier.java000066400000000000000000000043531412550063600257060ustar00rootroot00000000000000package org.mozilla.jss.tests; import java.math.BigInteger; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.ObjectIdentifier; public class BigObjectIdentifier { public static void main(String[] args) throws Exception { long[] oid_components_long = { 1L, 3L,6L,1L,4L,1L,5000L,9L,1L,1L,1526913300628L, 1L}; int[] oid_components_int = { 1, 3,6,1,4,1,2312,9,1,1,15269, 1, 1}; BigInteger[] oid_components_big_int = { new BigInteger("1"), new BigInteger("3"), new BigInteger("6"), new BigInteger("1"), new BigInteger("4"), new BigInteger("1"), new BigInteger("2312"), new BigInteger("9"), new BigInteger("1"), new BigInteger("152691330062899999999999997777788888888888888889999999999999999"), new BigInteger("1") }; String oidIn = "1.3.6.1.4.1.2312.9.1.152691330062899999999999997777788888888888888889999999999999999.1"; ObjectIdentifier oid = new ObjectIdentifier(oidIn); ObjectIdentifier fromDer = null; ObjectIdentifier fromStaticMethod = null; ObjectIdentifier fromComponentList = null; ObjectIdentifier fromComponentListInt = null; ObjectIdentifier fromComponentListBigInt = null; System.out.println("oid: " + oid.toString()); DerOutputStream out = new DerOutputStream(); oid.encode(out); DerInputStream in = new DerInputStream(out.toByteArray()); fromDer = new ObjectIdentifier(in); System.out.println("fromDer: " + fromDer.toString()); fromStaticMethod = ObjectIdentifier.getObjectIdentifier(oidIn); System.out.println("fromStaticMethod: " + fromStaticMethod.toString()); fromComponentList = new ObjectIdentifier(oid_components_long); System.out.println("fromComponentList: " + fromComponentList.toString()); fromComponentListInt = new ObjectIdentifier(oid_components_int); System.out.println("fromComponentListInt: " + fromComponentListInt); fromComponentListBigInt = new ObjectIdentifier(oid_components_big_int); System.out.println("fromComponentListBigInt: " + fromComponentListBigInt); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/CapabilitiesList.java000066400000000000000000000236701412550063600253030ustar00rootroot00000000000000package org.mozilla.jss.tests; import java.security.Security; import java.security.Provider; import java.util.*; import java.security.*; import javax.crypto.*; import java.security.Provider; import java.security.Security; import java.util.Enumeration; import java.util.Properties; import java.io.File; import java.io.FileWriter; import java.io.FileInputStream; import java.io.IOException; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.InitializationValues; import org.mozilla.jss.JSSProvider; import org.mozilla.jss.util.Password; import org.mozilla.jss.util.PasswordCallback; import org.mozilla.jss.util.PasswordCallbackInfo; import org.mozilla.jss.util.NullPasswordCallback; import org.mozilla.jss.crypto.AlreadyInitializedException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * List the available capabilities for ciphers, key agreement, macs, message * digests, signatures and other objects for the Mozilla-JSS provider. * * The listing is done via two methods: * 1) A brief enumeration from example given at page that can no longer be found * http://www.java2s.com/Code/Java/Security/ListAllProviderAndItsAlgorithms.html * 2) A verbose enumeration based on example 1 from Cryptography for Java by David Hook * * Initialization code is like the one in org.mozilla.jss.tests.HmacTest */ public class CapabilitiesList { /* Inner class to use existing system nss database */ public static class UseSystemDB { /* Same location in the Linux distros we have tested */ public static String NSS_DB_LOCATION = "/etc/pki/nssdb"; private UseSystemDB() {} /* Only a static method */ /* Method adapted from one used in the candlepin projects * https://github.com/candlepin/candlepin/pull/2370/files#diff-170cc2e1af322c9796d4d8fe20e32bb0R98 * an approach that was suggested by Alexander Scheel */ public static void addJSSProvider() throws Exception { Capabilities.logger.debug("Starting call to JSSProviderLoader.addProvider()..."); InitializationValues ivs = new InitializationValues(NSS_DB_LOCATION); ivs.noCertDB = true; ivs.installJSSProvider = true; ivs.initializeJavaOnly = false; CryptoManager.initialize(ivs); CryptoManager cm = CryptoManager.getInstance(); } } // start of the Capabilities inner class /** * List the available capabilities for ciphers, key agreement, macs, message * digests, signatures and other objects for the Mozilla-JSS provider. * * The listing is done via two methods: * 1) A brief enumeration from example given at page that can no longer be found * http://www.java2s.com/Code/Java/Security/ListAllProviderAndItsAlgorithms.html * 2) A verbose enumeration based on example 1 from Cryptography for Java by David Hook * * It incorporates code from org.mozilla.jss.tests.JSSProvider */ static class Capabilities { public static Logger logger = LoggerFactory.getLogger(CapabilitiesList.class); public static String briefFileBase = "listings/brief/Capabilities4"; public static String verboseFileBase = "listings/verbose/Capabilities4"; public Capabilities() { } /* List capabilites of the specified provider */ public void listCapabilities(FileWriter fw, Provider p) throws Exception { Set keySet = p.keySet(); assert(keySet != null); Iterator it = keySet.iterator(); assert(it != null); // In the verbose listing, we want to create a mapping from // an implementation onto all of its aliases. To do this in one // pass, we create a hashmap of strings (impl classes) to sets // (of aliases). HashMap> mapping = new HashMap<>(); while (it.hasNext()) { String entry = (String)it.next(); if (entry.startsWith("Alg.Alias.")) { String implementation = (String)p.get(entry); assert !implementation.startsWith("Alg.Alias."); // We need to do a little bit of "fixup" here. Each alias // (entry) has a "Alg.Alias" prefix and the next component // is the algorithm base class of choice. However, the // implementation elides this base class, so to prevent // duplicates-with-empty-sets, we need to go back and // move this base class over to the implementation part. String withoutPrefix = entry.replaceFirst("Alg.Alias.", ""); String factoryClass = withoutPrefix.substring(0, withoutPrefix.indexOf('.')); implementation = factoryClass + "." + implementation; if (mapping.get(implementation) == null) { mapping.put(implementation, new HashSet()); } mapping.get(implementation).add(withoutPrefix); } else { mapping.put(entry, new HashSet()); } } // To make the results predictable, sort both the top-level keys // and any inner aliases before printing them. ArrayList entries = new ArrayList(mapping.keySet()); Collections.sort(entries); for (String entry : entries) { String factoryClass = entry.substring(0, entry.indexOf('.')); String name = entry.substring(factoryClass.length()+1); assert(name != null); fw.write(String.format("\t %s : %s", factoryClass, name)); fw.write(System.lineSeparator()); if (mapping.get(entry) != null) { ArrayList subentries = new ArrayList(mapping.get(entry)); Collections.sort(subentries); for (String subentry : subentries) { fw.write(String.format("\t\t Alias: %s", subentry)); fw.write(System.lineSeparator()); } } } } /* Determine whether Mozilla-JSS provider was registered */ public boolean jssIsRegistered(Provider[] ps) throws Exception { Provider jssProvider = null; for (int i = 0; i < ps.length; i++) { Provider p = ps[i]; if (p.getName().equals("Mozilla-JSS")) { jssProvider = p; break; } } assert(jssProvider != null); assert(jssProvider.getName().equals("Mozilla-JSS")); assert(jssProvider instanceof org.mozilla.jss.JSSProvider); return (jssProvider != null); } public void addJssProvider() throws Exception { try { UseSystemDB.addJSSProvider(); } catch (Exception e) { e.printStackTrace(); System.out.println("Alternative method failed: keep going"); } // Validate that CryptoManager registers jss as a provider. if (!jssIsRegistered(Security.getProviders())) { throw new Exception("JSS is not registered"); } } public boolean createOutputDirs() throws Exception { /* Create hierarchy of directores for the results */ File dir4Listings = new File("listings"); dir4Listings.mkdir(); File dir4verboseListings = new File("listings/verbose"); dir4verboseListings.mkdir(); File dir4briefListings = new File("listings/brief"); dir4briefListings.mkdir(); return true; } /* List providers capabilities using the brief listing method which adds * results for each provider listed to the listings/brief directory */ public void listBrief(Provider[] ps) throws Exception { try { for (int i = 0; i < ps.length; i++) { String fileName = briefFileBase + ps[i].getName() + ".txt"; FileWriter fw = new FileWriter(new File(fileName)); for (Enumeration e = ps[i].keys(); e.hasMoreElements();) { fw.write(String.format("\t %s", e.nextElement())); fw.write(System.lineSeparator()); } fw.close(); File resultsFile = new File(fileName); assert(resultsFile.exists()); } } catch (Exception e) { logger.info("Exception caught in listBrief: " + e.getMessage(), e); logger.info("Keep going"); } } /* List providers capabilities using the verbose listing method which * adds results for each provider listed to the listings/verbose directory */ public void listVerbose(Provider[] ps) throws Exception { try { for (int i = 0; i < ps.length; i++) { String fileName = verboseFileBase + ps[i].getName() + ".txt"; FileWriter fw = new FileWriter(new File(fileName)); listCapabilities(fw, ps[i]); fw.close(); File resultsFile = new File(fileName); assert(resultsFile.exists()); } } catch (Exception e) { logger.info("Exception caught in listVerbose: " + e.getMessage(), e); logger.info("Keep going"); } } } public static void main(String[] args) throws Exception { Capabilities lister = new Capabilities(); if (!lister.createOutputDirs()) return; lister.addJssProvider(); Provider ps[] = Security.getProviders(); lister.listBrief(ps); lister.listVerbose(ps); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/CertificateChainTest.java000066400000000000000000000210341412550063600260730ustar00rootroot00000000000000package org.mozilla.jss.tests; import java.security.cert.X509Certificate; import java.util.Base64; import org.junit.Assert; import org.junit.Test; import org.mozilla.jss.netscape.security.x509.CertificateChain; import org.mozilla.jss.netscape.security.x509.X509CertImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class CertificateChainTest { public static Logger logger = LoggerFactory.getLogger(CertificateChainTest.class); public X509Certificate rootCA; public X509Certificate subCA; public X509Certificate admin; public CertificateChainTest() throws Exception { // Subject DN: CN=Root CA Signing Certificate, O=EXAMPLE // Issuer DN: CN=Root CA Signing Certificate, O=EXAMPLE rootCA = new X509CertImpl(Base64.getDecoder().decode( "MIIDRjCCAi6gAwIBAgIJAMHiDXjnZ1J6MA0GCSqGSIb3DQEBCwUAMDgxEDAOBgNV" + "BAoMB0VYQU1QTEUxJDAiBgNVBAMMG1Jvb3QgQ0EgU2lnbmluZyBDZXJ0aWZpY2F0" + "ZTAeFw0xOTAzMDUxNzQzMjFaFw0yMDAzMDQxNzQzMjFaMDgxEDAOBgNVBAoMB0VY" + "QU1QTEUxJDAiBgNVBAMMG1Jvb3QgQ0EgU2lnbmluZyBDZXJ0aWZpY2F0ZTCCASIw" + "DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMDv7ovkD+JVEdlLncYDnhzbLOz2" + "c3D37fobufnHHNwNOwfLZj8WdBCzwGJv+XGF+D2JIcKyYwYPR+HOg+xClhuuVleE" + "gMVvgxM+HcpM4heyBD2QczNo1dfXQRBy2AXvRn8Byh+Q6zbN7VoNu8ZaMQOxZx9m" + "EAiDZ7WxHVrEp2a4QrI6I9gKY6SyEHRzVT48JElLFokwhkMpF8vhgtj0Xxr5EEIY" + "yCMOzvZLtpeyH8PUri3Cv/hX1RZKjWqKLSJSKirnZLhZoEEzXtsOmoeeZBeRiabi" + "dPLsxqPfWFx4+BC7t5Vw5FaIt2mPh+q6bjZipO4uWz/p4a9wpqakuzgNsYUCAwEA" + "AaNTMFEwHQYDVR0OBBYEFCvlfY9OzAVsYpJEoqr7QfguO9v5MB8GA1UdIwQYMBaA" + "FCvlfY9OzAVsYpJEoqr7QfguO9v5MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN" + "AQELBQADggEBAHB1lWjT6bP1jAkk6eTVwBU2pGoGoYMGV3fWQGOmWQP5T7+nHKkU" + "jNMRACoC2hFlypwX8qQ70V5O4U+qrnxDP3EaT1zPsOB0x4DIIrpFgudL9EqnSbJ0" + "kvSz3awwO8x/Nvx7TatCncmTw9c14eqek2puhcQWvxHzWkaDHd9WxPrZJFftbSsn" + "ZGK2A/ybDCnUA5BDeCSDb5gufTd8gbS4wS1NwYcbbrQyHnLJlFcIF4aLkbYuX1bn" + "cYp8pQv3pZ3C/ofA+yBJvPELTaHjDC40MTdjFFfMQTPZswBX2iimoGQ/ProBGg7+" + "rLg2uk5AHff3oo/V1X0SSzo3IpvHh0jhg9I=" )); // Subject DN: CN=Subordinate CA Signing Certificate, O=EXAMPLE // Issuer DN: CN=Root CA Signing Certificate, O=EXAMPLE subCA = new X509CertImpl(Base64.getDecoder().decode( "MIIC8zCCAdsCCQCPJrl0/W/nMTANBgkqhkiG9w0BAQsFADA4MRAwDgYDVQQKDAdF" + "WEFNUExFMSQwIgYDVQQDDBtSb290IENBIFNpZ25pbmcgQ2VydGlmaWNhdGUwHhcN" + "MTkwMzA1MTg1MzMzWhcNMjAwMzA0MTg1MzMzWjA/MRAwDgYDVQQKDAdFWEFNUExF" + "MSswKQYDVQQDDCJTdWJvcmRpbmF0ZSBDQSBTaWduaW5nIENlcnRpZmljYXRlMIIB" + "IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzop7/TcsWElVMjzjaaAcj5KH" + "c9H6rqhFmOsL/VYdbNzTkZD3i5DVB4sFFEHTMwEoKKpBKh9hkY8laRUWjtidDJu2" + "+NBPLJa+k0Q+KUWIQko1rtgSjmCN+oMZFh7Mo8fV1WLSBnNjwbUrMeRKxOaR/roa" + "YgIwH5Ra6cxsVHGngAfrjXPtiuFp7qjzUbbRBBRP2LpKDk45RzllSLhz09qgo135" + "by2zErfUsWoma+dzvfWVI27um2DEzHMMAHELZM6BSJEYaGUW+y4cHQuuhz6Bo1YY" + "L6RHp6RhuMzlILN7a/XznS6Zc8OV/hRlkZVUUha6tqSQ/uXNTaefa6sGrRWNdQID" + "AQABMA0GCSqGSIb3DQEBCwUAA4IBAQAKLJq6bCZ8f/bI1OAeRNE7eIZliDnTjLqM" + "M3sG9gkWCp1l7UD5CLAbCaL6jFEuBAvkr88LYS4A0vuMAmMVsiSsFRTZNLmazts7" + "NZARuOYmzuNb/SZzhOBgypo6G96cqLhslzFtxXs+zJic2lQEDu+5+pcZCyETWoBT" + "kD9sAM2dM1I9//05UTJ5mzuLFmW3rhSjsrOuYHJjwagUVVAYDrIqNgNb/XSlmWbu" + "d1t9sKHgHzN2H0DIsKaoupPhTDUABrDuG3mRn1gI2xu1RlluaXZB7ZpUZAB/hMTV" + "8JPbHZeV08qYlfWJqhnUAZ0YQOx0yi5D98uhYB6Is/msBQ/YIbEi" )); // Subject DN: UID=admin, O=EXAMPLE // Issuer DN: CN=Subordinate CA Signing Certificate, O=EXAMPLE admin = new X509CertImpl(Base64.getDecoder().decode( "MIIC5DCCAcwCCQCh59LykL9CDTANBgkqhkiG9w0BAQsFADA/MRAwDgYDVQQKDAdF" + "WEFNUExFMSswKQYDVQQDDCJTdWJvcmRpbmF0ZSBDQSBTaWduaW5nIENlcnRpZmlj" + "YXRlMB4XDTE5MDMwNTIwMDQxNloXDTIwMDMwNDIwMDQxNlowKTEQMA4GA1UECgwH" + "RVhBTVBMRTEVMBMGCgmSJomT8ixkAQEMBWFkbWluMIIBIjANBgkqhkiG9w0BAQEF" + "AAOCAQ8AMIIBCgKCAQEA7QR+I7nLeGFntCajqIETKZ2MtpXdnrU3nkJawKwi1xQp" + "lYhFoVIqGqiX1+LfopemmR1bv2hcLt9uce4FG8jtELEF5KuCdCT99BSi8iVU+w0z" + "s4kCfUj9HvIcFhUO0dhkyVI//ZDh16xOi5AS3jqB0PtjgYbdrmufxXQhnyoeY9CM" + "N/w8OmN7mx2xUIApFP2LldU21rNSvly2Q0JbVDN2q7EENViYovvELW7zALGT5l/u" + "wVUsdkdgKY2C0ZHCh+aUDvDogywIALJIRxjcCU3Udx8Vfq/+MZCNccj6CPeCxNFv" + "L/wNtu+MpboF1jwNZB5jK9FPr3lXaH1aDdxoBSDMVwIDAQABMA0GCSqGSIb3DQEB" + "CwUAA4IBAQApkTNJMiCOYi9MI79kHFbEESd/ae+TTvHAd7sBIe5u1v5yK5Ij2opK" + "orY+gCVwNQOUlR7P/FIaY4eLVfPswqr3pl6O/DyqcuMLZofOHAzPEIBPFV/Qxcu1" + "WB1SDnSW61Wx7khVnWJQPgbcPVHdgTSS4vmUOw3YAsFAqzczth6bw/5sD19WLVu6" + "OYTSFGiofFLZXkidxZ7DIP2TUsaFJUEOkdoXlAImaHGpsCB/NXj2bWRmbzxcnMxd" + "jxttLewQofszMM0extB95n1KFv/bzbD+m9NM+aqvLOrzOg5rlcE5cbU07DVIycYs" + "fszFfR+9FvzA/AOpUzHg8y+ZX1rUts5f" )); } @Test public void testDefaultConstructor() throws Exception { CertificateChain chain = new CertificateChain(); Assert.assertEquals(0, chain.getCertificates().size()); } @Test public void testConstructorWithNullCert() throws Exception { try { new CertificateChain((X509Certificate) null); Assert.fail("Creating CertificateChain with null cert should fail"); } catch (IllegalArgumentException e) { Assert.assertEquals("Missing input certificate", e.getMessage()); } } @Test public void testConstructorWithRootCA() throws Exception { CertificateChain chain = new CertificateChain(rootCA); Assert.assertEquals(1, chain.getCertificates().size()); Assert.assertEquals(rootCA, chain.getCertificates().get(0)); } @Test public void testConstructorWithNullCertArray() throws Exception { try { new CertificateChain((X509Certificate[]) null); Assert.fail("Creating CertificateChain with null cert array should fail"); } catch (IllegalArgumentException e) { Assert.assertEquals("Missing input certificates", e.getMessage()); } } @Test public void testConstructorWithEmptyCertArray() throws Exception { CertificateChain chain = new CertificateChain(new X509Certificate[] {}); Assert.assertEquals(0, chain.getCertificates().size()); } @Test public void testConstructorWithOneCert() throws Exception { CertificateChain chain = new CertificateChain(new X509Certificate[] { rootCA }); Assert.assertEquals(1, chain.getCertificates().size()); Assert.assertEquals(rootCA, chain.getCertificates().get(0)); } @Test public void testConstructorWithTwoCerts() throws Exception { CertificateChain chain = new CertificateChain(new X509Certificate[] { rootCA, subCA }); Assert.assertEquals(2, chain.getCertificates().size()); Assert.assertEquals(rootCA, chain.getCertificates().get(0)); Assert.assertEquals(subCA, chain.getCertificates().get(1)); } @Test public void testGetterMethods() throws Exception { CertificateChain chain = new CertificateChain(new X509Certificate[] { rootCA, subCA, admin }); Assert.assertEquals(3, chain.getCertificates().size()); Assert.assertEquals(rootCA, chain.getFirstCertificate()); Assert.assertEquals(rootCA, chain.getCertificate(0)); Assert.assertEquals(subCA, chain.getCertificate(1)); Assert.assertEquals(admin, chain.getCertificate(2)); try { chain.getCertificate(3); Assert.fail("Getting cert #3 should fail"); } catch (IndexOutOfBoundsException e) { // failed as expected } X509Certificate[] certs = chain.getChain(); Assert.assertEquals(3, certs.length); Assert.assertEquals(rootCA, certs[0]); Assert.assertEquals(subCA, certs[1]); Assert.assertEquals(admin, certs[2]); } @Test public void testSorting() throws Exception { CertificateChain chain = new CertificateChain(new X509Certificate[] { admin, subCA, rootCA }); chain.sort(); Assert.assertEquals(3, chain.getCertificates().size()); Assert.assertEquals(rootCA, chain.getCertificate(0)); Assert.assertEquals(subCA, chain.getCertificate(1)); Assert.assertEquals(admin, chain.getCertificate(2)); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/ChainSortingTest.java000066400000000000000000000262541412550063600253070ustar00rootroot00000000000000package org.mozilla.jss.tests; import java.security.cert.X509Certificate; import java.util.Base64; import org.junit.Assert; import org.junit.Test; import org.mozilla.jss.netscape.security.util.Cert; import org.mozilla.jss.netscape.security.x509.X509CertImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ChainSortingTest { public static Logger logger = LoggerFactory.getLogger(ChainSortingTest.class); public X509Certificate rootCA; public X509Certificate subCA; public X509Certificate admin; public X509Certificate agent; public ChainSortingTest() throws Exception { // Subject DN: CN=Root CA Signing Certificate, O=EXAMPLE // Issuer DN: CN=Root CA Signing Certificate, O=EXAMPLE rootCA = new X509CertImpl(Base64.getDecoder().decode( "MIIDRjCCAi6gAwIBAgIJAMHiDXjnZ1J6MA0GCSqGSIb3DQEBCwUAMDgxEDAOBgNV" + "BAoMB0VYQU1QTEUxJDAiBgNVBAMMG1Jvb3QgQ0EgU2lnbmluZyBDZXJ0aWZpY2F0" + "ZTAeFw0xOTAzMDUxNzQzMjFaFw0yMDAzMDQxNzQzMjFaMDgxEDAOBgNVBAoMB0VY" + "QU1QTEUxJDAiBgNVBAMMG1Jvb3QgQ0EgU2lnbmluZyBDZXJ0aWZpY2F0ZTCCASIw" + "DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMDv7ovkD+JVEdlLncYDnhzbLOz2" + "c3D37fobufnHHNwNOwfLZj8WdBCzwGJv+XGF+D2JIcKyYwYPR+HOg+xClhuuVleE" + "gMVvgxM+HcpM4heyBD2QczNo1dfXQRBy2AXvRn8Byh+Q6zbN7VoNu8ZaMQOxZx9m" + "EAiDZ7WxHVrEp2a4QrI6I9gKY6SyEHRzVT48JElLFokwhkMpF8vhgtj0Xxr5EEIY" + "yCMOzvZLtpeyH8PUri3Cv/hX1RZKjWqKLSJSKirnZLhZoEEzXtsOmoeeZBeRiabi" + "dPLsxqPfWFx4+BC7t5Vw5FaIt2mPh+q6bjZipO4uWz/p4a9wpqakuzgNsYUCAwEA" + "AaNTMFEwHQYDVR0OBBYEFCvlfY9OzAVsYpJEoqr7QfguO9v5MB8GA1UdIwQYMBaA" + "FCvlfY9OzAVsYpJEoqr7QfguO9v5MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN" + "AQELBQADggEBAHB1lWjT6bP1jAkk6eTVwBU2pGoGoYMGV3fWQGOmWQP5T7+nHKkU" + "jNMRACoC2hFlypwX8qQ70V5O4U+qrnxDP3EaT1zPsOB0x4DIIrpFgudL9EqnSbJ0" + "kvSz3awwO8x/Nvx7TatCncmTw9c14eqek2puhcQWvxHzWkaDHd9WxPrZJFftbSsn" + "ZGK2A/ybDCnUA5BDeCSDb5gufTd8gbS4wS1NwYcbbrQyHnLJlFcIF4aLkbYuX1bn" + "cYp8pQv3pZ3C/ofA+yBJvPELTaHjDC40MTdjFFfMQTPZswBX2iimoGQ/ProBGg7+" + "rLg2uk5AHff3oo/V1X0SSzo3IpvHh0jhg9I=" )); // Subject DN: CN=Subordinate CA Signing Certificate, O=EXAMPLE // Issuer DN: CN=Root CA Signing Certificate, O=EXAMPLE subCA = new X509CertImpl(Base64.getDecoder().decode( "MIIC8zCCAdsCCQCPJrl0/W/nMTANBgkqhkiG9w0BAQsFADA4MRAwDgYDVQQKDAdF" + "WEFNUExFMSQwIgYDVQQDDBtSb290IENBIFNpZ25pbmcgQ2VydGlmaWNhdGUwHhcN" + "MTkwMzA1MTg1MzMzWhcNMjAwMzA0MTg1MzMzWjA/MRAwDgYDVQQKDAdFWEFNUExF" + "MSswKQYDVQQDDCJTdWJvcmRpbmF0ZSBDQSBTaWduaW5nIENlcnRpZmljYXRlMIIB" + "IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzop7/TcsWElVMjzjaaAcj5KH" + "c9H6rqhFmOsL/VYdbNzTkZD3i5DVB4sFFEHTMwEoKKpBKh9hkY8laRUWjtidDJu2" + "+NBPLJa+k0Q+KUWIQko1rtgSjmCN+oMZFh7Mo8fV1WLSBnNjwbUrMeRKxOaR/roa" + "YgIwH5Ra6cxsVHGngAfrjXPtiuFp7qjzUbbRBBRP2LpKDk45RzllSLhz09qgo135" + "by2zErfUsWoma+dzvfWVI27um2DEzHMMAHELZM6BSJEYaGUW+y4cHQuuhz6Bo1YY" + "L6RHp6RhuMzlILN7a/XznS6Zc8OV/hRlkZVUUha6tqSQ/uXNTaefa6sGrRWNdQID" + "AQABMA0GCSqGSIb3DQEBCwUAA4IBAQAKLJq6bCZ8f/bI1OAeRNE7eIZliDnTjLqM" + "M3sG9gkWCp1l7UD5CLAbCaL6jFEuBAvkr88LYS4A0vuMAmMVsiSsFRTZNLmazts7" + "NZARuOYmzuNb/SZzhOBgypo6G96cqLhslzFtxXs+zJic2lQEDu+5+pcZCyETWoBT" + "kD9sAM2dM1I9//05UTJ5mzuLFmW3rhSjsrOuYHJjwagUVVAYDrIqNgNb/XSlmWbu" + "d1t9sKHgHzN2H0DIsKaoupPhTDUABrDuG3mRn1gI2xu1RlluaXZB7ZpUZAB/hMTV" + "8JPbHZeV08qYlfWJqhnUAZ0YQOx0yi5D98uhYB6Is/msBQ/YIbEi" )); // Subject DN: UID=admin, O=EXAMPLE // Issuer DN: CN=Subordinate CA Signing Certificate, O=EXAMPLE admin = new X509CertImpl(Base64.getDecoder().decode( "MIIC5DCCAcwCCQCh59LykL9CDTANBgkqhkiG9w0BAQsFADA/MRAwDgYDVQQKDAdF" + "WEFNUExFMSswKQYDVQQDDCJTdWJvcmRpbmF0ZSBDQSBTaWduaW5nIENlcnRpZmlj" + "YXRlMB4XDTE5MDMwNTIwMDQxNloXDTIwMDMwNDIwMDQxNlowKTEQMA4GA1UECgwH" + "RVhBTVBMRTEVMBMGCgmSJomT8ixkAQEMBWFkbWluMIIBIjANBgkqhkiG9w0BAQEF" + "AAOCAQ8AMIIBCgKCAQEA7QR+I7nLeGFntCajqIETKZ2MtpXdnrU3nkJawKwi1xQp" + "lYhFoVIqGqiX1+LfopemmR1bv2hcLt9uce4FG8jtELEF5KuCdCT99BSi8iVU+w0z" + "s4kCfUj9HvIcFhUO0dhkyVI//ZDh16xOi5AS3jqB0PtjgYbdrmufxXQhnyoeY9CM" + "N/w8OmN7mx2xUIApFP2LldU21rNSvly2Q0JbVDN2q7EENViYovvELW7zALGT5l/u" + "wVUsdkdgKY2C0ZHCh+aUDvDogywIALJIRxjcCU3Udx8Vfq/+MZCNccj6CPeCxNFv" + "L/wNtu+MpboF1jwNZB5jK9FPr3lXaH1aDdxoBSDMVwIDAQABMA0GCSqGSIb3DQEB" + "CwUAA4IBAQApkTNJMiCOYi9MI79kHFbEESd/ae+TTvHAd7sBIe5u1v5yK5Ij2opK" + "orY+gCVwNQOUlR7P/FIaY4eLVfPswqr3pl6O/DyqcuMLZofOHAzPEIBPFV/Qxcu1" + "WB1SDnSW61Wx7khVnWJQPgbcPVHdgTSS4vmUOw3YAsFAqzczth6bw/5sD19WLVu6" + "OYTSFGiofFLZXkidxZ7DIP2TUsaFJUEOkdoXlAImaHGpsCB/NXj2bWRmbzxcnMxd" + "jxttLewQofszMM0extB95n1KFv/bzbD+m9NM+aqvLOrzOg5rlcE5cbU07DVIycYs" + "fszFfR+9FvzA/AOpUzHg8y+ZX1rUts5f" )); // Subject DN: UID=agent, O=EXAMPLE // Issuer DN: CN=Subordinate CA Signing Certificate, O=EXAMPLE agent = new X509CertImpl(Base64.getDecoder().decode( "MIIC5DCCAcwCCQCh59LykL9CDjANBgkqhkiG9w0BAQsFADA/MRAwDgYDVQQKDAdF" + "WEFNUExFMSswKQYDVQQDDCJTdWJvcmRpbmF0ZSBDQSBTaWduaW5nIENlcnRpZmlj" + "YXRlMB4XDTE5MDMwNTIwMzU1NVoXDTIwMDMwNDIwMzU1NVowKTEQMA4GA1UECgwH" + "RVhBTVBMRTEVMBMGCgmSJomT8ixkAQEMBWFnZW50MIIBIjANBgkqhkiG9w0BAQEF" + "AAOCAQ8AMIIBCgKCAQEA7c4d93Gw4c0eW88ALqlUP01qkTzwRFLGKExbeBAwAGIY" + "0c/c9sHFkRkEO5Fm+BeaX0qqdF5D7dk+yTJcnvbLa4YP0MC+iOBIAmRk9CZmfArM" + "GE6dmMtt2pmQb38VlyY+3Cmjhz779rfzepAkSdmeLFTUW1I1KUIZDUovuu58Ak6j" + "7V0Ri3V2iI8z5zLRqg1Ko517+vsr2nKeAUO+g2Zbcu8qb6uS3Qq7mrHaHg7ZZb+M" + "yyqdqmMmLW1SQnITyqVXV/KH3mbAfsdQPopODhdH1LpuEw9xU9hVG6tn+ihytPsU" + "7txSW2nFC3iSzL8FK1RSerWAN93hLHVf5q5XXVk87QIDAQABMA0GCSqGSIb3DQEB" + "CwUAA4IBAQCWPtQEoUMoSJY+gqnoJNqq7DzprBQOaBMV5KKA+Fo4mSn6MUetFLPl" + "/HD1Knub2DEEuALPq5H3O71Jfy1cscAq3sD9Zl2jPP4FvrC0ypQl/Q5bG/8QDM9p" + "1INSAdyzPsTY+Y/mKChF3HNCzssnDWWDzHr6gSI7wnlDrE2QQGdHIn2Znx4P47RH" + "MTFX3xumo1b8nTyjdJ2aW8T80i30SejDkmnN9XBp14D7fheGOlKeP2lCt5GDpkcF" + "mT4YgcaVtSxMQBn7QhWV3534BqAjE5a32DEuJ6SnZph1GaDFy/kMXbjV/n9igHDs" + "b5s4gPC9eTB38qG0y+8TDATxvJ7s2OOM" )); } @Test public void testNulLChain() throws Exception { logger.info("Testing null chain"); X509Certificate[] input = null; X509Certificate[] output = Cert.sortCertificateChain(input); X509Certificate[] expected = null; Assert.assertArrayEquals(expected, output); } @Test public void testEmptyChain() throws Exception { logger.info("Testing empty chain"); X509Certificate[] input = {}; X509Certificate[] output = Cert.sortCertificateChain(input); X509Certificate[] expected = {}; Assert.assertArrayEquals(expected, output); } @Test public void testOneLevelChain() throws Exception { logger.info("Testing one-level chain"); X509Certificate[] input = { rootCA }; X509Certificate[] output = Cert.sortCertificateChain(input); X509Certificate[] expected = { rootCA }; Assert.assertArrayEquals(expected, output); } @Test public void testTwoLevelOrderedChain() throws Exception { logger.info("Testing two-level ordered chain"); X509Certificate[] input = { rootCA, subCA }; X509Certificate[] output = Cert.sortCertificateChain(input); X509Certificate[] expected = { rootCA, subCA }; Assert.assertArrayEquals(expected, output); } @Test public void testTwoLevelUnorderedChain() throws Exception { logger.info("Testing two-level unordered chain"); X509Certificate[] input = { subCA, rootCA }; X509Certificate[] output = Cert.sortCertificateChain(input); X509Certificate[] expected = { rootCA, subCA }; Assert.assertArrayEquals(expected, output); } @Test public void testThreeLevelOrderedChain() throws Exception { logger.info("Testing three-level ordered chain"); X509Certificate[] input = { rootCA, subCA, admin }; X509Certificate[] output = Cert.sortCertificateChain(input); X509Certificate[] expected = { rootCA, subCA, admin }; Assert.assertArrayEquals(expected, output); } @Test public void testThreeLevelUnorderedChain() throws Exception { logger.info("Testing three-level unordered chain"); X509Certificate[] input = { admin, subCA, rootCA }; X509Certificate[] output = Cert.sortCertificateChain(input); X509Certificate[] expected = { rootCA, subCA, admin }; Assert.assertArrayEquals(expected, output); } @Test public void testThreeLevelReverseChain() throws Exception { logger.info("Testing three-level reverse chain"); X509Certificate[] input = { subCA, rootCA, admin }; X509Certificate[] output = Cert.sortCertificateChain(input, true); X509Certificate[] expected = { admin, subCA, rootCA }; Assert.assertArrayEquals(expected, output); } @Test public void testPartialChain() throws Exception { logger.info("Testing partial chain"); X509Certificate[] input = { admin, subCA }; X509Certificate[] output = Cert.sortCertificateChain(input); X509Certificate[] expected = { subCA, admin }; Assert.assertArrayEquals(expected, output); } @Test public void testDuplicateChain() throws Exception { logger.info("Testing chain with duplicate certificates"); X509Certificate[] input = { rootCA, subCA, subCA, admin }; try { Cert.sortCertificateChain(input); Assert.fail(); } catch (Exception e) { String message = e.getMessage(); String expected = "Duplicate certificate: " + subCA.getSubjectDN(); Assert.assertEquals(expected, message); } } @Test public void testBranchedChain() throws Exception { logger.info("Testing branched chain"); X509Certificate[] input = { rootCA, subCA, admin, agent}; try { Cert.sortCertificateChain(input); Assert.fail(); } catch (Exception e) { String message = e.getMessage(); String expected = "Branched chain: " + subCA.getSubjectDN(); Assert.assertEquals(expected, message); } } @Test public void testBrokenChain() throws Exception { logger.info("Testing broken chain"); X509Certificate[] input = { rootCA, admin }; try { Cert.sortCertificateChain(input); Assert.fail(); } catch (Exception e) { String message = e.getMessage(); String expected = "Multiple leaf certificates: [" + rootCA.getSubjectDN() + "], [" + admin.getSubjectDN() + "]"; Assert.assertEquals(expected, message); } } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/ClassServer.java000077500000000000000000000075401412550063600243130ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.io.BufferedReader; import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ServerSocket; import java.net.Socket; import java.util.Vector; /* * ClassServer.java -- JSSE_SSLServer implements this * class. */ public abstract class ClassServer implements Runnable { private ServerSocket server = null; private Vector supportedCiphers = new Vector<>(); /** * Constructs a ClassServer based on ss */ protected ClassServer(ServerSocket ss) { server = ss; newListener(); } /** * The "listen" thread that accepts a connection to the * server, parses the header to obtain the file name * and sends back the bytes for the file (or error * if the file is not found or the response was malformed). */ @Override public void run() { Socket socket = null; boolean socketListenStatus = true; // accept a connection while ( socketListenStatus ) { try { socket = server.accept(); } catch (Exception ex) { System.exit(1); } newListener(); //try to read some bytes, to allow the handshake to go through try { InputStream is = socket.getInputStream(); BufferedReader bir = new BufferedReader( new InputStreamReader(is)); String socketData = bir.readLine(); if ( socketData.equals("null") ) socketListenStatus = false; else if ( socketData != null ) supportedCiphers.add(socketData); socket.close(); } catch(EOFException e) { } catch(IOException ex) { } catch(NullPointerException npe) { socketListenStatus = false; } } try { server.close(); } catch (Exception ex) { System.exit(1); } System.out.println("Server exiting"); System.out.println("-------------------------------------------" + "-------------"); System.out.println("Summary of JSS client to JSSE server " + "communication test :"); System.out.println("-------------------------------------------" + "-------------"); System.out.println("supportedCiphers.size " + supportedCiphers.size()); System.out.println("Constants.jssCiphersSuites "+ Constants.jssCipherSuites.length); for ( int i=0; i<(supportedCiphers.size()-1); i++ ) { System.out.print(i + " SC " + supportedCiphers.elementAt(i)); for ( int j=0; j<(Constants.jssCipherSuites.length); j++ ) { if (Integer.parseInt(supportedCiphers.elementAt(i)) == Constants.jssCipherSuites[j].value ) { System.out.print(" JSSC "); System.out.println(" ["+ i +"]\t" + Constants.jssCipherSuites[j].name); System.out.flush(); } } } System.out.println("-------------------------------------------" + "-------------"); System.out.flush(); if( !socketListenStatus ) { System.exit(0); } } /** * Create a new thread to listen. */ private void newListener() { (new Thread(this)).start(); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/CloseDBs.java000066400000000000000000000042631412550063600235110ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.math.BigInteger; import java.util.Enumeration; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.crypto.CryptoStore; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.X509Certificate; public final class CloseDBs extends org.mozilla.jss.DatabaseCloser { public CloseDBs() throws Exception { super(); } public static void main(String args[]) { int i; try { if(args.length != 1) { System.err.println("Usage: CloseDBs "); System.exit(0); } CryptoManager manager = CryptoManager.getInstance(); Enumeration tokens = manager.getAllTokens(); CryptoStore store; X509Certificate certs[]; java.security.PrivateKey keys[]; while (tokens.hasMoreElements()) { CryptoToken token = tokens.nextElement(); store = token.getCryptoStore(); System.out.println("Token: "+token.getName()); certs = store.getCertificates(); System.out.println("Certs:"); for(i=0; i < certs.length; i++) { System.out.println( certs[i].getNickname() ); } keys = store.getPrivateKeys(); System.out.println("Keys:"); try { for(i=0; i < keys.length; i++) { System.out.println(new BigInteger(1, keys[i].getEncoded())); } } catch (Exception ex) { System.out.println(ex.getMessage()); } } System.out.println("Closing databases..."); try { (new CloseDBs()).closeDatabases(); } catch (Exception ex) { System.out.println(ex.getMessage()); System.exit(1); } System.out.println("Databases are closed."); System.exit(0); } catch(Exception e) { e.printStackTrace(); System.exit(1); } } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/Constants.java000077500000000000000000000331471412550063600240350ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import org.mozilla.jss.ssl.*; /** * Holds immutable values for JSS Tests. * */ public interface Constants { /** Debug level for all tests */ public static int debug_level = 1; public static final class cipher { int value; /* hex value */ String name; cipher(int v, String n) { value = v; name = n; } /* * returns the string representation of the ciphersuite OR * returns null if the ciphersuite is not found */ public static final String cipherToString(int aCipher ) { for (int i = 0; i < Constants.jssCipherSuites.length; i++) { if (aCipher == Constants.jssCipherSuites[i].value) { return Constants.jssCipherSuites[i].name; } } return null; } /* * returns the integer value of the ciphersuite OR * returns -1 if the ciphersuite is not found. */ public static final int stringToCipher(String sCipher ) { for (int i = 0; i < Constants.jssCipherSuites.length; i++) { if (sCipher.compareToIgnoreCase( Constants.jssCipherSuites[i].name) == 0) { return Constants.jssCipherSuites[i].value; } } return -1; } } /** * The following have been deprecated * * SSL3_RSA_WITH_RC4_128_MD5 * SSL3_RSA_WITH_RC4_128_SHA * SSL3_DHE_RSA_WITH_3DES_EDE_CBC_SHA * SSL3_DHE_DSS_WITH_3DES_EDE_CBC_SHA * SL3_RSA_WITH_3DES_EDE_CBC_SHA * SSL3_DHE_RSA_WITH_DES_CBC_SHA * SSL3_DHE_DSS_WITH_DES_CBC_SHA * SSL3_RSA_WITH_DES_CBC_SHA * SSL3_RSA_WITH_NULL_SHA * SSL3_RSA_WITH_NULL_MD5 * SSL3_RSA_WITH_RC4_128_MD5 * SSL3_RSA_WITH_3DES_EDE_CBC_SHA * SSL3_RSA_WITH_DES_CBC_SHA * SSL3_RSA_WITH_NULL_MD5 */ /* cipherSuites Supported by JSS */ public static final cipher jssCipherSuites[] = { /*0 */ new cipher(SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA"), /*1 */ new cipher(SSLSocket.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA"), /*2 */ new cipher(SSLSocket.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA"), /*3 */ new cipher(SSLSocket.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA, "TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA"), /*4 */ new cipher(SSLSocket.TLS_DHE_RSA_WITH_AES_256_CBC_SHA, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"), /*5 */ new cipher(SSLSocket.TLS_DHE_DSS_WITH_AES_256_CBC_SHA, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA"), /*6 */ new cipher(SSLSocket.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA, "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA"), /*7 */ new cipher(SSLSocket.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA, "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"), /*8 */ new cipher(SSLSocket.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, "TLS_RSA_WITH_CAMELLIA_256_CBC_SHA"), /*9 */ new cipher(SSLSocket.TLS_RSA_WITH_AES_256_CBC_SHA, "TLS_RSA_WITH_AES_256_CBC_SHA"), /*10 */ new cipher(SSLSocket.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"), /*11 */ new cipher(SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"), /*12 */ new cipher(SSLSocket.TLS_ECDHE_RSA_WITH_RC4_128_SHA, "TLS_ECDHE_RSA_WITH_RC4_128_SHA"), /*13 */ new cipher(SSLSocket.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"), /*14 */ new cipher(SSLSocket.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA"), /*15 */ new cipher(SSLSocket.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA, "TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA"), /*16 */ new cipher(SSLSocket.TLS_DHE_DSS_WITH_RC4_128_SHA, "TLS_DHE_DSS_WITH_RC4_128_SHA"), /*17 */ new cipher(SSLSocket.TLS_DHE_RSA_WITH_AES_128_CBC_SHA, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"), /*18 */ new cipher(SSLSocket.TLS_DHE_DSS_WITH_AES_128_CBC_SHA, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA"), /*19 */ new cipher(SSLSocket.TLS_ECDH_RSA_WITH_RC4_128_SHA, "TLS_ECDH_RSA_WITH_RC4_128_SHA"), /*20 */ new cipher(SSLSocket.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA, "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA"), /*21 */ new cipher(SSLSocket.TLS_ECDH_ECDSA_WITH_RC4_128_SHA, "TLS_ECDH_ECDSA_WITH_RC4_128_SHA"), /*22 */ new cipher(SSLSocket.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA, "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA"), /*23 */ new cipher(SSLSocket.TLS_RSA_WITH_SEED_CBC_SHA, "TLS_RSA_WITH_SEED_CBC_SHA"), /*24 */ new cipher(SSLSocket.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, "TLS_RSA_WITH_CAMELLIA_128_CBC_SHA"), /*25 */ new cipher(SSLSocket.SSL3_RSA_WITH_RC4_128_MD5, "SSL3_RSA_WITH_RC4_128_MD5"), /*26 */ new cipher(SSLSocket.SSL3_RSA_WITH_RC4_128_SHA, "SSL3_RSA_WITH_RC4_128_SHA"), /*27 */ new cipher(SSLSocket.TLS_RSA_WITH_AES_128_CBC_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA"), /*28 */ new cipher(SSLSocket.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"), /*29 */ new cipher(SSLSocket.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"), /*30 */ new cipher(SSLSocket.SSL3_DHE_RSA_WITH_3DES_EDE_CBC_SHA, "SSL3_DHE_RSA_WITH_3DES_EDE_CBC_SHA"), /*31 */ new cipher(SSLSocket.SSL3_DHE_DSS_WITH_3DES_EDE_CBC_SHA, "SSL3_DHE_DSS_WITH_3DES_EDE_CBC_SHA"), /*32 */ new cipher(SSLSocket.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA, "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA"), /*33 */ new cipher(SSLSocket.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA, "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA"), /*34 */ new cipher(SSLSocket.SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA"), /*35 */ new cipher(SSLSocket.SSL3_RSA_WITH_3DES_EDE_CBC_SHA, "SSL3_RSA_WITH_3DES_EDE_CBC_SHA"), /*36 */ new cipher(SSLSocket.SSL3_DHE_RSA_WITH_DES_CBC_SHA, "SSL3_DHE_RSA_WITH_DES_CBC_SHA"), /*37 */ new cipher(SSLSocket.SSL3_DHE_DSS_WITH_DES_CBC_SHA, "SSL3_DHE_DSS_WITH_DES_CBC_SHA"), /*38 */ new cipher(SSLSocket.SSL_RSA_FIPS_WITH_DES_CBC_SHA, "SSL_RSA_FIPS_WITH_DES_CBC_SHA"), /*39 */ new cipher(SSLSocket.SSL3_RSA_WITH_DES_CBC_SHA, "SSL3_RSA_WITH_DES_CBC_SHA"), /*40 */ new cipher(SSLSocket.TLS_RSA_EXPORT1024_WITH_RC4_56_SHA, "TLS_RSA_EXPORT1024_WITH_RC4_56_SHA"), /*41 */ new cipher(SSLSocket.TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA, "TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA"), /*42 */ new cipher(SSLSocket.SSL3_RSA_EXPORT_WITH_RC4_40_MD5, "SSL3_RSA_EXPORT_WITH_RC4_40_MD5"), /*43 */ new cipher(SSLSocket.SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5, "SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5"), /*44 */ new cipher(SSLSocket.TLS_ECDHE_ECDSA_WITH_NULL_SHA, "TLS_ECDHE_ECDSA_WITH_NULL_SHA"), /*45 */ new cipher(SSLSocket.TLS_ECDHE_RSA_WITH_NULL_SHA, "TLS_ECDHE_RSA_WITH_NULL_SHA"), /*46 */ new cipher(SSLSocket.TLS_ECDH_RSA_WITH_NULL_SHA, "TLS_ECDH_RSA_WITH_NULL_SHA"), /*47 */ new cipher(SSLSocket.TLS_ECDH_ECDSA_WITH_NULL_SHA, "TLS_ECDH_ECDSA_WITH_NULL_SHA"), /*48 */ new cipher(SSLSocket.SSL3_RSA_WITH_NULL_SHA, "SSL3_RSA_WITH_NULL_SHA"), /*49 */ new cipher(SSLSocket.SSL3_RSA_WITH_NULL_MD5, "SSL3_RSA_WITH_NULL_MD5"), /*50 */ new cipher(SSLSocket.TLS_RSA_WITH_NULL_SHA256, "TLS_RSA_WITH_NULL_SHA256"), /*51 */ new cipher(SSLSocket.TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS_RSA_WITH_AES_128_CBC_SHA256"), /*52 */ new cipher(SSLSocket.TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS_RSA_WITH_AES_256_CBC_SHA256"), /*53*/ new cipher(SSLSocket.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"), /*54*/ new cipher(SSLSocket.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"), /*55*/ new cipher(SSLSocket.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"), /*56*/ new cipher(SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"), /*57*/ new cipher(SSLSocket.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"), /*58*/ new cipher(SSLSocket.TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS_RSA_WITH_AES_128_GCM_SHA256"), /*59*/ new cipher(SSLSocket.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"), /*60*/ new cipher(SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"), /*61*/ new cipher(SSLSocket.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"), /** /* SSL2 ciphersuites are here for legacy purposes. * you should call SSLSocket.enableSSL2Default(false) during your setup. * to disable all SSL2 ciphersuites. **/ /*62*/ new cipher(SSLSocket.SSL2_RC4_128_WITH_MD5, "SSL2_RC4_128_WITH_MD5"), /*63*/ new cipher(SSLSocket.SSL2_RC2_128_CBC_WITH_MD5, "SSL2_RC2_128_CBC_WITH_MD5"), /*64*/ new cipher(SSLSocket.SSL2_DES_192_EDE3_CBC_WITH_MD5, "SSL2_DES_192_EDE3_CBC_WITH_MD5"), /*65*/ new cipher(SSLSocket.SSL2_DES_64_CBC_WITH_MD5, "SSL2_DES_64_CBC_WITH_MD5"), /*66*/ new cipher(SSLSocket.SSL2_RC4_128_EXPORT40_WITH_MD5, "SSL2_RC4_128_EXPORT40_WITH_MD5"), /*67*/ new cipher(SSLSocket.SSL2_RC2_128_CBC_EXPORT40_WITH_MD5, "SSL2_RC2_128_CBC_EXPORT40_WITH_MD5"), /*68*/ new cipher(SSLSocket.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"), /*69*/ new cipher(SSLSocket.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256, "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256"), /*70*/ new cipher(SSLSocket.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"), /*71*/ new cipher(SSLSocket.TLS_RSA_WITH_NULL_SHA256, "TLS_RSA_WITH_NULL_SHA256"), /*72*/ new cipher(SSLSocket.TLS_RSA_WITH_AES_128_CBC_SHA256, "TLS_RSA_WITH_AES_128_CBC_SHA256"), /*73*/ new cipher(SSLSocket.TLS_RSA_WITH_AES_256_CBC_SHA256, "TLS_RSA_WITH_AES_256_CBC_SHA256"), /*74*/ new cipher(SSLSocket.TLS_RSA_WITH_SEED_CBC_SHA, "TLS_RSA_WITH_SEED_CBC_SHA"), /*75*/ new cipher(SSLSocket.TLS_RSA_WITH_AES_128_GCM_SHA256, "TLS_RSA_WITH_AES_128_GCM_SHA256"), /*76*/ new cipher(SSLSocket.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256"), /*77*/ new cipher(SSLSocket.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256, "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256"), /*78*/ new cipher(SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"), /*79*/ new cipher(SSLSocket.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"), /*80*/ new cipher(SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"), /*81*/ new cipher(SSLSocket.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256, "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256"), /*82*/ new cipher(SSLSocket.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"), /*83*/ new cipher(SSLSocket.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256, "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256"), /*84*/ new cipher(SSLSocket.TLS_RSA_WITH_AES_256_GCM_SHA384, "TLS_RSA_WITH_AES_256_GCM_SHA384"), /*85*/ new cipher(SSLSocket.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384"), /*86*/ new cipher(SSLSocket.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384, "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384"), /*87*/ new cipher(SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"), /*88*/ new cipher(SSLSocket.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"), /*89*/ new cipher(SSLSocket.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"), /*90*/ new cipher(SSLSocket.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384"), /*91*/ new cipher(SSLSocket.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256, "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256"), /*92*/ new cipher(SSLSocket.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, "TLS_DHE_PSK_WITH_AES_128_GCM_SHA256"), /*93*/ new cipher(SSLSocket.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384, "TLS_DHE_PSK_WITH_AES_256_GCM_SHA384"), // TLSv1_3 /*94*/ new cipher(SSLSocket.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"), /*95*/ new cipher(SSLSocket.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"), /*96*/ new cipher(SSLSocket.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256, "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256"), /*97*/ new cipher(SSLSocket.TLS_AES_128_GCM_SHA256, "TLS_AES_128_GCM_SHA256"), /*98*/ new cipher(SSLSocket.TLS_AES_256_GCM_SHA384, "TLS_AES_256_GCM_SHA384"), /*99*/ new cipher(SSLSocket.TLS_CHACHA20_POLY1305_SHA256, "TLS_CHACHA20_POLY1305_SHA256"), /*100*/ new cipher(SSLSocket.TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256"), /*101*/ new cipher(SSLSocket.TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256"), /*102*/ new cipher(SSLSocket.TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256, "TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256"), /*103*/ new cipher(SSLSocket.TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256, "TLS_ECDHE_PSK_WITH_AES_128_GCM_SHA256") }; /** Cipher supported by JSSE (JDK 1.5.x) */ public static String [] sslciphersarray_jdk150 = { // These ciphers must always pass "SSL_RSA_WITH_RC4_128_MD5", "SSL_RSA_WITH_RC4_128_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA", "SSL_RSA_WITH_DES_CBC_SHA", "SSL_RSA_WITH_3DES_EDE_CBC_SHA", "SSL_RSA_EXPORT_WITH_RC4_40_MD5", "SSL_RSA_WITH_NULL_MD5", }; /** Cipher supported by JSSE (JDK 1.4.x) */ public static String [] sslciphersarray_jdk142 = { "SSL_RSA_WITH_RC4_128_MD5", "SSL_RSA_WITH_RC4_128_SHA", "TLS_RSA_WITH_AES_128_CBC_SHA", "SSL_RSA_WITH_DES_CBC_SHA", "SSL_RSA_WITH_3DES_EDE_CBC_SHA", "SSL_RSA_EXPORT_WITH_RC4_40_MD5", "SSL_RSA_WITH_NULL_MD5", }; } jss-5.0.0/src/test/java/org/mozilla/jss/tests/ConverterTestUtil.java000066400000000000000000000012651412550063600255170ustar00rootroot00000000000000package org.mozilla.jss.tests; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.x509.AVAValueConverter; public class ConverterTestUtil { public static byte[] convert(AVAValueConverter converter, String string, byte[] tags) throws Exception { DerOutputStream os = new DerOutputStream(); DerValue value = converter.getValue(string, tags); value.encode(os); return os.toByteArray(); } public static byte[] convert(AVAValueConverter converter, String string) throws Exception { return convert(converter, string, null); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/CrossHMACTest.java000077500000000000000000000154401412550063600244370ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.security.MessageDigest; import org.mozilla.jss.CryptoManager; import java.security.Security; import java.security.Provider; import javax.crypto.*; import javax.crypto.spec.*; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.SecretKeyFacade; import org.mozilla.jss.util.PasswordCallback; /** * HMAC is a hash function based message authentication code. * CrossHMACTest compares the HMAC created by Mozilla, IBM and Sun JCE. * * @author Sandeep.Konchady@Sun.COM * @version 1.0 */ public class CrossHMACTest { private CryptoManager cm; /** * JSS crypto provider name. */ static final String MOZ_PROVIDER_NAME = "Mozilla-JSS"; /** * List all the HMAC Algorithms that JSS implements. */ static final String JSS_HMAC_Algs[] = {"HmacSHA1", "HmacSHA256", "HmacSHA384", "HmacSHA512" }; public CrossHMACTest(String[] argv) throws Exception { if (argv.length < 1) { System.out.println( "Usage: java org.mozilla.jss.tests.CrossHMACTest " + " [password file only needed in FIPS mode]"); System.exit(1); } cm = CryptoManager.getInstance(); if (cm.FIPSEnabled() == true) { System.out.println("\n\t\tFIPS enabled.\n"); if (argv.length == 2) { CryptoToken tok = cm.getInternalCryptoToken(); System.out.println("logging in to token: " + tok.getName()); PasswordCallback cb = new FilePasswordCallback(argv[1]); tok.login(cb); } } } public boolean compareHMAC(String alg, SecretKeyFacade sk, String clearText) throws Exception { byte[] providerHmacOut; byte[] mozillaHmacOut; boolean bTested = false; //Get the Mozilla HMAC Mac mozillaHmac = Mac.getInstance(alg, MOZ_PROVIDER_NAME); mozillaHmac.init(sk); mozillaHmac.update(clearText.getBytes()); mozillaHmacOut = mozillaHmac.doFinal(); // loop through all configured providers; if they support the // algorithm compare the result to Mozilla's HMAC Provider[] providers = Security.getProviders("Mac." + alg); String provider = null; for (int i = 0; i < providers.length; ++i) { provider = providers[i].getName(); //System.out.println ("Testing provider " + provider); if (provider.equals(MOZ_PROVIDER_NAME)) { continue; } Mac providerHmac = Mac.getInstance(alg, provider); providerHmac.init(sk); providerHmac.update(clearText.getBytes()); providerHmacOut = providerHmac.doFinal(); if (MessageDigest.isEqual(mozillaHmacOut, providerHmacOut)) { System.out.println(provider + " and " + MOZ_PROVIDER_NAME + " give same " + alg); bTested = true; } else { throw new Exception("ERROR: " + provider + " and " + MOZ_PROVIDER_NAME + " give different " + alg); } } return bTested; } public void doHMAC(String alg, SecretKeyFacade sk, String clearText) throws Exception { byte[] mozillaHmacOut; //Get the Mozilla HMAC Mac mozillaHmac = Mac.getInstance(alg, MOZ_PROVIDER_NAME); mozillaHmac.init(sk); mozillaHmacOut = mozillaHmac.doFinal(clearText.getBytes()); if (mozillaHmacOut.length == mozillaHmac.getMacLength()) { System.out.println(MOZ_PROVIDER_NAME + " supports " + mozillaHmac.getAlgorithm() + " and the output size is " + mozillaHmac.getMacLength()); } else { throw new Exception("ERROR: hmac output size is " + mozillaHmacOut.length + ", should be " + mozillaHmac.getMacLength()); } } public boolean fipsMode() { return cm.FIPSEnabled(); } /** * Main test method. * @param argv */ public static void main(String[] argv) { try { CrossHMACTest hmacTest = new CrossHMACTest(argv); //The secret key must be a JSS key. That is, it must be an //instanceof org.mozilla.jss.crypto.SecretKeyFacade. //Generate the secret key using PKCS # 5 password Based Encryption //we have to specify a salt and an iteration count. PBEKeySpec pbeKeySpec; SecretKeyFactory keyFac; SecretKeyFacade sk; byte[] salt = { (byte) 0x0a, (byte) 0x6d, (byte) 0x07, (byte) 0xba, (byte) 0x1e, (byte) 0xbd, (byte) 0x72, (byte) 0xf1 }; int iterationCount = 7; pbeKeySpec = new PBEKeySpec("password".toCharArray(), salt, iterationCount); keyFac = SecretKeyFactory.getInstance("PBEWithSHA1AndDES3", "Mozilla-JSS"); sk = (SecretKeyFacade) keyFac.generateSecret(pbeKeySpec); ///////////////////////////////////////////////////////////// // Test all available algorithms ///////////////////////////////////////////////////////////// String clearText = new String("FireFox and Thunderbird rule"); for (int i = 0; i < JSS_HMAC_Algs.length; i++) { if (hmacTest.fipsMode()) { //In FIPS Mode only test JSS due to NSS prevents //key data from being extracted above the //NSS cryptographic boundary when FIPS mode //is enabled. //note there is a bug with HmacSHA512 in fipsmode. //https://bugzilla.mozilla.org/show_bug.cgi?id=436907 if (!JSS_HMAC_Algs[i].equals("HmacSHA512")) { hmacTest.doHMAC(JSS_HMAC_Algs[i], sk, clearText); } } else { // compare MOZ_PROVIDER_NAME implementation with all // providers that also support the given algorithm if (!hmacTest.compareHMAC( JSS_HMAC_Algs[i], sk, clearText)) { // no provider to compare results with so just test JSS hmacTest.doHMAC(JSS_HMAC_Algs[i], sk, clearText); } } } } catch (Exception e) { e.printStackTrace(); System.exit(1); } System.exit(0); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/DEROutputStreamTests.java000066400000000000000000000047161412550063600261100ustar00rootroot00000000000000package org.mozilla.jss.tests; import org.mozilla.jss.netscape.security.util.*; public class DEROutputStreamTests { public static void assert_f(boolean expr, String location) { if (!expr) { System.err.println("Assertion: " + location); assert(expr); } } public static void testInteger(int value, byte[] expected) throws Exception { DerOutputStream out = new DerOutputStream(); BigInt num = new BigInt(value); out.putInteger(num); byte[] actual = out.toByteArray(); assert_f(actual.length == expected.length, "value=" + value); for (int i = 0; i < actual.length; i++) { assert_f(actual[i] == expected[i], "value=" + value + "|i=" + i); } } public static void testIntegers() throws Exception { int[] values = {0, 127, 128, 256}; byte[][] expected = {{0x02, 0x01, 0x00}, {0x02, 0x01, 0x7F}, {0x02, 0x02, 0x00, (byte) 0x80}, {0x02, 0x02, 0x01, 0x00}}; assert_f(values.length == expected.length, "testIntegers test cases"); for (int i = 0; i < values.length; i++ ) { testInteger(values[i], expected[i]); } } public static void testEnumeration(int value, byte[] expected) throws Exception { DerOutputStream out = new DerOutputStream(); out.putEnumerated(value); byte[] actual = out.toByteArray(); assert_f(actual.length == expected.length, "value=" + value); for (int i = 0; i < actual.length; i++ ) { assert_f(actual[i] == expected[i], "value=" + value + "|i=" + i); } } public static void testEnumerations() throws Exception { int[] values = {0, 1, 127, 128, 256, -128, -129}; byte[][] expected = {{0x0A, 0x01, 0x00}, {0x0A, 0x01, 0x01}, {0x0A, 0x01, 0x7F}, {0x0A, 0x02, 0x00, (byte) 0x80}, {0x0A, 0x02, 0x01, 0x00}, {0x0A, 0x01, (byte) 0x80}, {0x0A, 0x02, (byte) 0xFF, 0x7F}}; assert(values.length == expected.length); for (int i = 0; i < values.length; i++ ) { testEnumeration(values[i], expected[i]); } } public static void main(String[] args) throws Exception { testIntegers(); testEnumerations(); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/DigestTest.java000066400000000000000000000112501412550063600241240ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.io.FileInputStream; import java.security.MessageDigest; import java.security.Provider; import java.security.Security; public class DigestTest { /** * This is the name of the JSS crypto provider for use with * MessageDigest.getInstance(). */ static final String MOZ_PROVIDER_NAME = "Mozilla-JSS"; /** * List all the Digest Algorithms that JSS implements. */ static final String JSS_Digest_Algs[] = { "SHA-256", "SHA-384","SHA-512" }; public static boolean messageDigestCompare(String alg, byte[] toBeDigested) throws Exception { byte[] otherDigestOut; byte[] mozillaDigestOut; boolean bTested = false; // get the digest for the Mozilla-JSS provider java.security.MessageDigest mozillaDigest = java.security.MessageDigest.getInstance(alg, MOZ_PROVIDER_NAME); mozillaDigestOut = mozillaDigest.digest(toBeDigested); // loop through all the providers that support the algorithm // compare the result to Mozilla-JSS's digest Provider[] providers = Security.getProviders("MessageDigest." + alg); String provider = null; for (int i = 0; i < providers.length; ++i) { provider = providers[i].getName(); if (provider.equals(MOZ_PROVIDER_NAME)) { continue; } java.security.MessageDigest otherDigest = java.security.MessageDigest.getInstance(alg, provider); otherDigestOut = otherDigest.digest(toBeDigested); if( MessageDigest.isEqual(mozillaDigestOut, otherDigestOut) ) { System.out.println(provider + " and " + MOZ_PROVIDER_NAME + " give same " + alg + " message digests"); bTested = true; } else { throw new Exception("ERROR: " + provider + " and " + MOZ_PROVIDER_NAME + " give different " + alg + " message digests"); } } return bTested; } public static boolean testJSSDigest(String alg, byte[] toBeDigested) throws Exception { byte[] mozillaDigestOut; java.security.MessageDigest mozillaDigest = java.security.MessageDigest.getInstance(alg, MOZ_PROVIDER_NAME); mozillaDigestOut = mozillaDigest.digest(toBeDigested); if( mozillaDigestOut.length == mozillaDigest.getDigestLength() ) { System.out.println(mozillaDigest.getAlgorithm() + " " + " digest output size is " + mozillaDigestOut.length); } else { throw new Exception("ERROR: digest output size is "+ mozillaDigestOut.length + ", should be "+ mozillaDigest.getDigestLength() ); } return true; } public static void main(String []argv) { try { if( argv.length != 2 ) { System.out.println( "Usage: java org.mozilla.jss.tests.DigestTest " + " "); System.exit(1); } byte[] toBeDigested; int read; try (FileInputStream fis = new FileInputStream(argv[1])) { toBeDigested = new byte[fis.available()]; read = fis.read(toBeDigested); } System.out.println(read + " bytes to be digested"); ///////////////////////////////////////////////////////////// // Test all available algorithms ///////////////////////////////////////////////////////////// String javaVersion = System.getProperty("java.version"); System.out.println("The Java version is: " + javaVersion); for (int i = 0; i < JSS_Digest_Algs.length; i++) { // compare Mozilla-JSS implementation with all providers // that also support the given algorithm if (messageDigestCompare(JSS_Digest_Algs[i], toBeDigested) == false) { // no provider to compare results with testJSSDigest(JSS_Digest_Algs[i], toBeDigested); } } //HMAC examples in org.mozilla.jss.tests.HMACTest } catch( Exception e ) { e.printStackTrace(); System.exit(1); } System.exit(0); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/EmptyDerValue.java000066400000000000000000000010551412550063600245750ustar00rootroot00000000000000package org.mozilla.jss.tests; import org.mozilla.jss.netscape.security.util.DerValue; /* * Regression test: check that a zero-length derValue doesn't create a parsing * exception. * * Fixed by Fraser Tweedale in https://github.com/dogtagpki/jss/pull/89 * * Upstream Issue: https://pagure.io/dogtagpki/issue/3079 */ class EmptyDerValue { public static void main(String[] args) throws Exception { byte[] bytes = { 0x04, 0x00 }; DerValue derVal = new DerValue(bytes); System.out.println(derVal.getOctetString()); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/EnumerationZeroTest.java000066400000000000000000000176071412550063600260470ustar00rootroot00000000000000/** * Copyright (c) 2009 - 2018 Red Hat, Inc. * * This software is licensed to you under the GNU General Public License, * version 2 (GPLv2). There is NO WARRANTY for this software, express or * implied, including the implied warranties of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 * along with this software; if not, see * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. * * Red Hat trademarks are not licensed under GPLv2. No permission is * granted to use or replicate Red Hat trademarks that are incorporated * in this software or its documentation. * * Submitted by Alex Wood as an attachment to BZ#1582323. Used with * permission. */ package org.mozilla.jss.tests; import org.mozilla.jss.JSSProvider; import org.mozilla.jss.netscape.security.util.BitArray; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.x509.AuthorityKeyIdentifierExtension; import org.mozilla.jss.netscape.security.x509.CRLExtensions; import org.mozilla.jss.netscape.security.x509.CRLNumberExtension; import org.mozilla.jss.netscape.security.x509.CRLReasonExtension; import org.mozilla.jss.netscape.security.x509.Extension; import org.mozilla.jss.netscape.security.x509.KeyIdentifier; import org.mozilla.jss.netscape.security.x509.RevocationReason; import org.mozilla.jss.netscape.security.x509.RevokedCertImpl; import org.mozilla.jss.netscape.security.x509.RevokedCertificate; import org.mozilla.jss.netscape.security.x509.X500Name; import org.mozilla.jss.netscape.security.x509.X509CRLImpl; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.Security; import java.security.cert.CertificateFactory; import java.security.cert.X509CRL; import java.security.interfaces.RSAPublicKey; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; /** Class to demonstrate DER encoding failure when using an ASN.1 enumerated type with a value of zero. * * RFC 5280's section 5.3.1 lists the valid values for certificate revocation codes: * * CRLReason ::= ENUMERATED { * unspecified (0), * keyCompromise (1), * cACompromise (2), * affiliationChanged (3), * superseded (4), * cessationOfOperation (5), * certificateHold (6), * -- value 7 is not used * removeFromCRL (8), * privilegeWithdrawn (9), * aACompromise (10) } * */ public class EnumerationZeroTest { static { // Satellite 6 is only supported on 64 bit architectures Security.addProvider(new JSSProvider()); } private EnumerationZeroTest() { } public static String toHex(byte[] bytes) { StringBuilder sb = new StringBuilder(bytes.length * 2); for (byte b : bytes) { sb.append(String.format("%02x", b)); } return sb.toString(); } /** * Calculate the KeyIdentifier for an RSAPublicKey and place it in an AuthorityKeyIdentifier extension. * * Java encodes RSA public keys using the SubjectPublicKeyInfo type described in RFC 5280. *
     * SubjectPublicKeyInfo  ::=  SEQUENCE  {
     *   algorithm            AlgorithmIdentifier,
     *   subjectPublicKey     BIT STRING  }
     *
     * AlgorithmIdentifier  ::=  SEQUENCE  {
     *   algorithm               OBJECT IDENTIFIER,
     *   parameters              ANY DEFINED BY algorithm OPTIONAL  }
     * 
* * A KeyIdentifier is a SHA-1 digest of the subjectPublicKey bit string from the ASN.1 above. * * @param key the RSAPublicKey to use * @return an AuthorityKeyIdentifierExtension based on the key * @throws IOException if we can't construct a MessageDigest object. */ public static AuthorityKeyIdentifierExtension buildAuthorityKeyIdentifier(RSAPublicKey key) throws IOException { try { MessageDigest d = MessageDigest.getInstance("SHA-1"); byte[] encodedKey = key.getEncoded(); DerInputStream s = new DerValue(encodedKey).toDerInputStream(); // Skip the first item in the sequence, AlgorithmIdentifier. // The parameter, startLen, is required for skipSequence although it's unused. s.skipSequence(0); // Get the subjectPublicKey bit string BitArray b = s.getUnalignedBitString(); byte[] digest = d.digest(b.toByteArray()); KeyIdentifier ki = new KeyIdentifier(digest); return new AuthorityKeyIdentifierExtension(ki, null, null); } catch (NoSuchAlgorithmException e) { throw new IOException("Could not find SHA1 implementation", e); } } /** * Output the DER encoding of a CRLExtension for examination */ public static void outputExtension(CRLReasonExtension ext) throws Exception { ByteArrayOutputStream resultBytesOut = new ByteArrayOutputStream(); ext.encode(resultBytesOut); byte[] encodedBytes = resultBytesOut.toByteArray(); System.out.print("Full encoded extension: " + toHex(encodedBytes)); Extension reasonExt = new Extension(new DerValue(encodedBytes)); System.out.print("\tEncoded CRL Reason: " + toHex(reasonExt.getExtensionValue())); DerValue reasonValue = new DerValue(reasonExt.getExtensionValue()); System.out.println("\tReason value: " + reasonValue.getEnumerated()); } /** * Build a CRL using JSS * @param useZero whether or not to try creating a CRLEntry with the reason set to "unspecified" * @return an X509CRL object * @throws Exception if anything goes wrong */ public static X509CRL buildCrl(boolean useZero) throws Exception { KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA"); generator.initialize(2048); KeyPair kp = generator.generateKeyPair(); List revokedCerts = new ArrayList<>(); for (int i = 0; i <= 10; i++) { // 7 is an unused value in the enumeration if (i == 7 || (i == 0 && !useZero)) { continue; } CRLReasonExtension reasonExt = new CRLReasonExtension(RevocationReason.fromInt(i)); outputExtension(reasonExt); CRLExtensions entryExtensions = new CRLExtensions(); entryExtensions.add(reasonExt); revokedCerts.add( new RevokedCertImpl(BigInteger.valueOf((long) i), new Date(), entryExtensions)); } CRLExtensions crlExtensions = new CRLExtensions(); crlExtensions.add(new CRLNumberExtension(BigInteger.ONE)); crlExtensions.add(buildAuthorityKeyIdentifier((RSAPublicKey) kp.getPublic())); X500Name issuer = new X500Name("CN=Test"); Date now = new Date(); Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.DAY_OF_MONTH, 365); Date until = calendar.getTime(); X509CRLImpl crlImpl = new X509CRLImpl( issuer, now, until, revokedCerts.toArray(new RevokedCertificate[] {}), crlExtensions ); crlImpl.sign(kp.getPrivate(), "SHA256withRSA"); CertificateFactory cf = CertificateFactory.getInstance("X.509"); byte[] data = crlImpl.getEncoded(); return (X509CRL) cf.generateCRL(new ByteArrayInputStream(data)); } public static void main(String[] args) throws Exception { X509CRL crl = buildCrl(false); System.out.println(crl.toString()); buildCrl(true); // will throw exception } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/FilePasswordCallback.java000066400000000000000000000026551412550063600260750ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.io.FileInputStream; import java.io.IOException; import java.util.Properties; import org.mozilla.jss.util.Password; import org.mozilla.jss.util.PasswordCallback; import org.mozilla.jss.util.PasswordCallbackInfo; /** */ public class FilePasswordCallback implements PasswordCallback { private Properties passwords; public FilePasswordCallback(String filename) throws IOException { passwords = new Properties(); try (FileInputStream in = new FileInputStream(filename)) { passwords.load(in); } } /** */ @Override public Password getPasswordFirstAttempt(PasswordCallbackInfo info) throws PasswordCallback.GiveUpException { String pw = passwords.getProperty(info.getName()); if( pw == null ) { throw new PasswordCallback.GiveUpException(); } else { System.out.println("***FilePasswordCallback returns " + pw); return new Password(pw.toCharArray()); } } /** */ @Override public Password getPasswordAgain(PasswordCallbackInfo info) throws PasswordCallback.GiveUpException { throw new PasswordCallback.GiveUpException(); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/FipsTest.java000066400000000000000000000135331412550063600236140ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.util.Enumeration; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.InitializationValues; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.pkcs11.PK11Module; import org.mozilla.jss.pkcs11.PK11Token; import org.mozilla.jss.util.PasswordCallback; public class FipsTest { public static void main(String args[]) { try { if( args.length < 2 ) { System.out.println("Usage: FipsTest "); return; } String dbdir = args[0]; String fipsmode = args[1]; String password = ""; if (args.length == 3) { password = args[2]; System.out.println("The password file " +password); } InitializationValues vals = new InitializationValues(dbdir); System.out.println("output of Initilization values "); System.out.println("Manufacturer ID: " + vals.getManufacturerID()); System.out.println("Library: " + vals.getLibraryDescription()); System.out.println("Internal Slot: " + vals.getInternalSlotDescription()); System.out.println("Internal Token: " + vals.getInternalTokenDescription()); System.out.println("Key Storage Slot: " + vals.getFIPSKeyStorageSlotDescription()); System.out.println("Key Storage Token: " + vals.getInternalKeyStorageTokenDescription()); System.out.println("FIPS Slot: " + vals.getFIPSSlotDescription()); System.out.println("FIPS Key Storage: " + vals.getFIPSKeyStorageSlotDescription()); if (fipsmode.equalsIgnoreCase("enable")) { vals.fipsMode = InitializationValues.FIPSMode.ENABLED; } else if (fipsmode.equalsIgnoreCase("disable")){ vals.fipsMode = InitializationValues.FIPSMode.DISABLED; } else { vals.fipsMode = InitializationValues.FIPSMode.UNCHANGED; } CryptoManager.initialize(vals); CryptoManager cm = CryptoManager.getInstance(); if (cm.FIPSEnabled() == true ) { System.out.println("\n\t\tFIPS enabled\n"); } else { System.out.println("\n\t\tFIPS not enabled\n"); } Enumeration modules = cm.getModules(); System.out.println("\nListing of Modules:"); while (modules.hasMoreElements()) { System.out.println("\t"+ modules.nextElement().getName() ); } CryptoToken tok; String tokenName; Enumeration tokens = cm.getAllTokens(); System.out.println("\nAll Tokens:"); while (tokens.hasMoreElements()) { tok = tokens.nextElement(); System.out.print("\t" + tok.getName()); if (tok.needsLogin() == true){ System.out.println("\t - Needs login.\n"); } else { System.out.println("\t - Does not need login.\n"); } } tokens = cm.getExternalTokens(); System.out.println("\nExternal Tokens:"); while(tokens.hasMoreElements()) { System.out.println("\t"+ tokens.nextElement().getName() ); } /* find the Internal Key Storage token */ if (cm.FIPSEnabled() == true ) { tokenName = vals.getFIPSSlotDescription(); } else { tokenName = vals.getInternalKeyStorageTokenDescription(); } /* truncate to 32 bytes and remove trailing white space*/ tokenName = tokenName.substring(0, 32); tokenName = tokenName.trim(); System.out.println("\nFinding the Internal Key Storage token: "+ tokenName); tok = cm.getTokenByName(tokenName); if( ((PK11Token)tok).isInternalKeyStorageToken() && tok.equals(cm.getInternalKeyStorageToken()) ) { System.out.println("Good, "+tok.getName()+", knows it is " + "the internal Key Storage Token"); } else { System.out.println("ERROR: "+tok.getName()+", doesn't know"+ " it is the internal key storage token"); } if (!password.equals("")) { System.out.println("logging in to the Token: " + tok.getName()); PasswordCallback cb = new FilePasswordCallback(password); tok.login(cb); System.out.println("logged in to the Token: " + tok.getName()); } /* find the Internal Crypto token */ if (cm.FIPSEnabled() == true ) { tokenName = vals.getFIPSSlotDescription(); } else { tokenName = vals.getInternalTokenDescription(); } /* truncate to 32 bytes and remove trailing white space*/ tokenName = tokenName.substring(0, 32); tokenName = tokenName.trim(); System.out.println("\nFinding the Internal Crypto token: " + tokenName); tok = cm.getTokenByName(tokenName); if( ((PK11Token)tok).isInternalCryptoToken() && tok.equals(cm.getInternalCryptoToken() )) { System.out.println("Good, "+tok.getName()+ ", knows it is the internal Crypto token"); } else { System.out.println("ERROR: "+tok.getName()+ ", doesn't know that it is the internal Crypto token"); } System.exit(0); } catch( Exception e ) { e.printStackTrace(); System.exit(1); } } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/GenerateTestCert.java000077500000000000000000000301411412550063600252600ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** * GenerateTestCert is a class for generating SSL test certificates for * the JSS tests (all.pl). You should use certutil to create * your certificates. * */ package org.mozilla.jss.tests; import java.security.KeyPair; import java.security.PrivateKey; import java.security.PublicKey; import java.util.Calendar; import java.util.Date; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.BOOLEAN; import org.mozilla.jss.asn1.INTEGER; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.InternalCertificate; import org.mozilla.jss.crypto.SignatureAlgorithm; import org.mozilla.jss.crypto.X509Certificate; import org.mozilla.jss.pkix.cert.Certificate; import org.mozilla.jss.pkix.cert.CertificateInfo; import org.mozilla.jss.pkix.cert.Extension; import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; import org.mozilla.jss.pkix.primitive.Name; import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo; import org.mozilla.jss.util.PasswordCallback; public class GenerateTestCert { private X509Certificate nssServerCert, nssClientCert; static final private String CACERT_NICKNAME = "JSSCATestCert"; static final private String SERVERCERT_NICKNAME = "JSSTestServerCert"; static final private String CLIENTCERT_NICKNAME = "JSSTestClientCert"; private String keyType = "RSA"; private int keyLength = 4096; private SignatureAlgorithm sigAlg = SignatureAlgorithm.RSASignatureWithSHA256Digest; /** * Main method for testing and generating cert pairs. */ public static void main(String[] args) throws Exception { GenerateTestCert gtc = new GenerateTestCert(); if ( args.length > 0 ) { gtc.doIt(args); } else { gtc.usage(); } } public void usage() { System.out.println("USAGE: " + "java org.mozilla.jss.tests.GenerateTestCert " + " [hostname] " + "[Signature Alg] [CAcertNickname] " + "[ServerCertNickname] [ClientCertNickName]"); System.out.println("This program creates self signed Certificates." + "They are only meant for testing and should never be " + "used in production. " + "\nThe default nicknames:" + "\n\tCA certificate: " + CACERT_NICKNAME + "\n\tServer certificate: " + SERVERCERT_NICKNAME + "\n\tClient certificate: " + CLIENTCERT_NICKNAME); System.out.println("Signature algorithm values:\n" + "\tSHA-1/RSA" + "\tSHA-256/RSA" + "\tSHA-384/RSA" + "\tSHA-512/RSA" + "\tSHA-1/DSA" + "\tSHA-1/EC" + "\tSHA-256/EC" + "\tSHA-384/EC" + "\tSHA-512/EC"); System.exit(1); } private void setSigAlg(String alg) { if (alg.equalsIgnoreCase("SHA-1/RSA")) { sigAlg = SignatureAlgorithm.RSASignatureWithSHA1Digest; } else if (alg.equalsIgnoreCase("SHA-256/RSA")) { sigAlg = SignatureAlgorithm.RSASignatureWithSHA256Digest; } else if (alg.equalsIgnoreCase("SHA-384/RSA")) { sigAlg = SignatureAlgorithm.RSASignatureWithSHA384Digest; } else if (alg.equalsIgnoreCase("SHA-512/RSA")) { sigAlg = SignatureAlgorithm.RSASignatureWithSHA512Digest; } else if (alg.equalsIgnoreCase("SHA-1/DSA")) { sigAlg = SignatureAlgorithm.DSASignatureWithSHA1Digest; } else if (alg.equalsIgnoreCase("SHA-1/EC")) { sigAlg = SignatureAlgorithm.ECSignatureWithSHA1Digest; } else if (alg.equalsIgnoreCase("SHA-256/EC")) { sigAlg = SignatureAlgorithm.ECSignatureWithSHA256Digest; } else if (alg.equalsIgnoreCase("SHA-384/EC")) { sigAlg = SignatureAlgorithm.ECSignatureWithSHA384Digest; } else if (alg.equalsIgnoreCase("SHA-512/EC")) { sigAlg = SignatureAlgorithm.ECSignatureWithSHA512Digest; } else { usage(); } if (alg.endsWith("RSA")) { keyType = "RSA"; } else if (alg.endsWith("DSA")) { keyType = "DSA"; keyLength = 1024; } else if (alg.endsWith("EC")) { keyType = "EC"; keyLength = 256; } else { usage(); } } /** * Based on the input parameters, generate a cert * pair. */ private void doIt(String[] args) throws Exception { String caCertNick = CACERT_NICKNAME; String serverCertNick = SERVERCERT_NICKNAME; String clientCertNick = CLIENTCERT_NICKNAME; if ( args.length < 3 ) { usage(); } try { CryptoManager cm = CryptoManager.getInstance(); CryptoToken tok = cm.getInternalKeyStorageToken(); PasswordCallback cb = new FilePasswordCallback(args[1]); tok.login(cb); int serialNum = Integer.parseInt(args[2]); X509Certificate[] permCerts = cm.getPermCerts(); int originalPermCerts = permCerts.length; System.out.println("Number of certificates stored in the " + " database: " + originalPermCerts); String hostname = "localhost"; if (args.length > 4) { hostname = args[3]; } String alg = "SHA-256/RSA"; if (args.length > 5) { alg = args[4]; } setSigAlg(alg); X509Certificate[] certs; if (args.length > 6) { caCertNick = args[5]; } /* ensure certificate does not already exists */ certs = cm.findCertsByNickname(caCertNick); if (certs.length > 0) { System.out.println(caCertNick + " already exists!"); System.exit(1); } if (args.length > 7) { serverCertNick = args[6]; } certs = cm.findCertsByNickname(serverCertNick); if (certs.length > 0) { System.out.println(serverCertNick + " already exists!"); System.exit(1); } if (args.length == 8) { clientCertNick = args[7]; } certs = cm.findCertsByNickname(clientCertNick); if (certs.length > 0) { System.out.println(clientCertNick + " already exists!"); System.exit(1); } // generate CA cert java.security.KeyPairGenerator kpg = java.security.KeyPairGenerator.getInstance( keyType, "Mozilla-JSS"); kpg.initialize(keyLength); KeyPair caPair = kpg.genKeyPair(); SEQUENCE extensions = new SEQUENCE(); extensions.addElement(makeBasicConstraintsExtension()); Certificate caCert = makeCert("CACert", "CACert", serialNum, caPair.getPrivate(), caPair.getPublic(), serialNum, extensions); X509Certificate nssCaCert = cm.importUserCACertPackage( ASN1Util.encode(caCert), caCertNick); InternalCertificate intern = (InternalCertificate)nssCaCert; intern.setSSLTrust( InternalCertificate.TRUSTED_CA | InternalCertificate.TRUSTED_CLIENT_CA | InternalCertificate.VALID_CA); // generate server cert kpg.initialize(keyLength); KeyPair serverPair = kpg.genKeyPair(); Certificate serverCert = makeCert("CACert", hostname, serialNum+1, caPair.getPrivate(), serverPair.getPublic(), serialNum, null); nssServerCert = cm.importCertPackage( ASN1Util.encode(serverCert), serverCertNick); // generate client auth cert kpg.initialize(keyLength); KeyPair clientPair = kpg.genKeyPair(); Certificate clientCert = makeCert("CACert", "ClientCert", serialNum+2, caPair.getPrivate(), clientPair.getPublic(), serialNum, null); nssClientCert = cm.importCertPackage( ASN1Util.encode(clientCert), clientCertNick); System.out.println("\nThis program created certificates with \n" + "following cert nicknames:" + "\n\t" + caCertNick + "\n\t" + serverCertNick + "\n\t" + clientCertNick); permCerts = cm.getPermCerts(); if ( (originalPermCerts + 3) != permCerts.length) { System.out.println("Error there should be three more " + " certificates stored in the database"); System.exit(1); } else { System.out.println("Number of certificates stored in the " + " database: " + permCerts.length); } /* ensure certificates exists */ certs = cm.findCertsByNickname(caCertNick); if (certs.length == 0) { System.out.println(caCertNick + " should exist!"); System.exit(1); } certs = cm.findCertsByNickname(serverCertNick); if (certs.length == 0) { System.out.println(serverCertNick + " should exist!"); System.exit(1); } certs = cm.findCertsByNickname(clientCertNick); if (certs.length == 0) { System.out.println(clientCertNick + " should exist!"); System.exit(1); } } catch(Exception e) { e.printStackTrace(); System.exit(1); } System.exit(0); } /** * Make basic extension. */ private Extension makeBasicConstraintsExtension() throws Exception { SEQUENCE bc = new SEQUENCE(); bc.addElement( new BOOLEAN(true) ); // cA OBJECT_IDENTIFIER bcOID = new OBJECT_IDENTIFIER( new long[] {2, 5, 29, 19}); // from RFC 2459 OCTET_STRING enc = new OCTET_STRING(ASN1Util.encode(bc)); return new Extension(bcOID, true, enc); } /** * Method that generates a certificate for given credential * * @param issuerName * @param subjectName * @param serialNumber * @param privKey * @param pubKey * @param rand * @param extensions * @throws java.lang.Exception * @return */ private Certificate makeCert(String issuerName, String subjectName, int serialNumber, PrivateKey privKey, PublicKey pubKey, int rand, SEQUENCE extensions) throws Exception { AlgorithmIdentifier sigAlgID = new AlgorithmIdentifier(sigAlg.toOID()); Name issuer = new Name(); issuer.addCountryName("US"); issuer.addOrganizationName("Mozilla"); issuer.addOrganizationalUnitName("JSS Testing" + rand); issuer.addCommonName(issuerName); Name subject = new Name(); subject.addCountryName("US"); subject.addOrganizationName("Mozilla"); subject.addOrganizationalUnitName("JSS Testing" + rand); subject.addCommonName(subjectName); Calendar cal = Calendar.getInstance(); Date notBefore = cal.getTime(); cal.add(Calendar.YEAR, 1); Date notAfter = cal.getTime(); SubjectPublicKeyInfo.Template spkiTemp = new SubjectPublicKeyInfo.Template(); SubjectPublicKeyInfo spki = (SubjectPublicKeyInfo) ASN1Util.decode(spkiTemp, pubKey.getEncoded()); CertificateInfo info = new CertificateInfo( CertificateInfo.v3, new INTEGER(serialNumber), sigAlgID, issuer, notBefore, notAfter, subject, spki); if( extensions != null ) { info.setExtensions(extensions); } return new Certificate(info, privKey, sigAlg); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/GenericValueConverterTest.java000066400000000000000000000110311412550063600271430ustar00rootroot00000000000000package org.mozilla.jss.tests; import org.junit.Assert; import org.junit.Test; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.x509.GenericValueConverter; public class GenericValueConverterTest { @Test public void testEmptyString() throws Exception { String string = ""; System.out.println("Converting: [" + string + "]"); byte[] expected = JSSUtil.encode(DerValue.tag_PrintableString, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = ConverterTestUtil.convert(new GenericValueConverter(), string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testNullCharacters() throws Exception { String string = StringTestUtil.NULL_CHARS; System.out.println("Converting: [" + StringTestUtil.toString(string.getBytes()) + "]"); byte[] expected = JSSUtil.encode(DerValue.tag_IA5String, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = ConverterTestUtil.convert(new GenericValueConverter(), string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testPrintableCharacters() throws Exception { String string = StringTestUtil.PRINTABLE_CHARS; System.out.println("Converting: [" + string + "]"); byte[] expected = JSSUtil.encode(DerValue.tag_PrintableString, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = ConverterTestUtil.convert(new GenericValueConverter(), string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testControlCharacters() throws Exception { String string = StringTestUtil.CONTROL_CHARS; System.out.println("Converting: [" + StringTestUtil.toString(string.getBytes()) + "]"); byte[] expected = JSSUtil.encode(DerValue.tag_IA5String, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = ConverterTestUtil.convert(new GenericValueConverter(), string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testMultibyteCharacters() throws Exception { String string = StringTestUtil.MULTIBYTE_CHARS; System.out.println("Converting: [" + string + "]"); byte[] expected = JSSUtil.encode(DerValue.tag_BMPString, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = ConverterTestUtil.convert(new GenericValueConverter(), string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); actual = StringTestUtil.normalizeUnicode(actual); System.out.println(" - norm. : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testPrintableCharactersWithTags() throws Exception { String string = StringTestUtil.PRINTABLE_CHARS; System.out.println("Converting: [" + string + "]"); byte[] expected = JSSUtil.encode(DerValue.tag_T61String, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = ConverterTestUtil.convert(new GenericValueConverter(), string, new byte[] { DerValue.tag_T61String, DerValue.tag_UniversalString }); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testMultibyteCharactersWithTags() throws Exception { String string = StringTestUtil.MULTIBYTE_CHARS; System.out.println("Converting: [" + string + "]"); byte[] expected = JSSUtil.encode(DerValue.tag_UniversalString, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = ConverterTestUtil.convert(new GenericValueConverter(), string, new byte[] { DerValue.tag_T61String, DerValue.tag_UniversalString }); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/HmacTest.java000066400000000000000000000046661412550063600235720ustar00rootroot00000000000000 package org.mozilla.jss.tests; import java.security.Key; import javax.crypto.KeyGenerator; import javax.crypto.Mac; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.SecretKeySpec; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.InitializationValues; import org.mozilla.jss.crypto.CryptoToken; public class HmacTest { private static final String INTERNAL_KEY_STORAGE_TOKEN = new InitializationValues("").getInternalKeyStorageTokenDescription().trim(); private static final String NSS_DATABASE_DIR = "sql:data"; private static final String PROVIDER = "Mozilla-JSS"; public static void main(String[] args) throws Exception { String algorithm = "hmac-sha1"; configureCrypto(args); Mac mac = Mac.getInstance(algorithm, PROVIDER); byte[] keyData = new byte[16]; Key key = importHmacSha1Key(keyData); mac.init(key); doHMAC(mac,"Dogtag rules!"); System.out.println("Done"); } private static void configureCrypto(String[] args) throws Exception { CryptoManager cryptoManager = CryptoManager.getInstance(); CryptoToken cryptoToken = cryptoManager.getTokenByName(INTERNAL_KEY_STORAGE_TOKEN); cryptoManager.setThreadToken(cryptoToken); } private static Key importHmacSha1Key(byte[] key) throws Exception { SecretKeyFactory factory = SecretKeyFactory.getInstance("HmacSHA1", "Mozilla-JSS"); return factory.generateSecret(new SecretKeySpec(key, "HmacSHA1")); } private static synchronized Key getWrappingKey() throws Exception { final String keyGenAlgorithm = "AES"; final int wrappingKeyLength = 256; KeyGenerator keyGen = KeyGenerator.getInstance(keyGenAlgorithm, PROVIDER); keyGen.init(wrappingKeyLength); return keyGen.generateKey(); } public static void doHMAC(Mac mozillaHmac, String clearText) throws Exception { byte[] mozillaHmacOut; //Get the Mozilla HMAC mozillaHmacOut = mozillaHmac.doFinal(clearText.getBytes()); if (mozillaHmacOut.length == mozillaHmac.getMacLength()) { System.out.println(PROVIDER + " supports " + mozillaHmac.getAlgorithm() + " and the output size is " + mozillaHmac.getMacLength()); } else { throw new Exception("ERROR: hmac output size is " + mozillaHmacOut.length + ", should be " + mozillaHmac.getMacLength()); } } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/IA5StringConverterTest.java000066400000000000000000000062161412550063600263500ustar00rootroot00000000000000package org.mozilla.jss.tests; import org.junit.Assert; import org.junit.Test; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.x509.IA5StringConverter; public class IA5StringConverterTest { @Test public void testEmptyString() throws Exception { String string = ""; System.out.println("Converting: [" + string + "]"); byte[] expected = JSSUtil.encode(DerValue.tag_IA5String, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = ConverterTestUtil.convert(new IA5StringConverter(), string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testNullCharacters() throws Exception { String string = StringTestUtil.NULL_CHARS; System.out.println("Converting: [" + StringTestUtil.toString(string.getBytes()) + "]"); byte[] expected = JSSUtil.encode(DerValue.tag_IA5String, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = ConverterTestUtil.convert(new IA5StringConverter(), string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testPrintableCharacters() throws Exception { String string = StringTestUtil.PRINTABLE_CHARS; System.out.println("Converting: [" + string + "]"); byte[] expected = JSSUtil.encode(DerValue.tag_IA5String, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = ConverterTestUtil.convert(new IA5StringConverter(), string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testControlCharacters() throws Exception { String string = StringTestUtil.CONTROL_CHARS; System.out.println("Converting: [" + StringTestUtil.toString(string.getBytes()) + "]"); byte[] expected = JSSUtil.encode(DerValue.tag_IA5String, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = ConverterTestUtil.convert(new IA5StringConverter(), string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testMultibyteCharacters() throws Exception { String string = StringTestUtil.MULTIBYTE_CHARS; System.out.println("Converting: [" + string + "]"); System.out.println(" - expected: IllegalArgumentException"); try { byte[] actual = ConverterTestUtil.convert(new IA5StringConverter(), string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.fail(); } catch (Exception e) { System.out.println(" - actual : " + e.getClass().getSimpleName()); Assert.assertTrue(e instanceof IllegalArgumentException); } } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/IA5StringTest.java000066400000000000000000000210061412550063600244520ustar00rootroot00000000000000package org.mozilla.jss.tests; import java.io.IOException; import org.junit.Assert; import org.junit.Test; import org.mozilla.jss.netscape.security.util.DerValue; public class IA5StringTest { public byte tag = DerValue.tag_IA5String; @Test public void testEncodingEmptyString() throws Exception { String string = ""; System.out.println("Encoding: [" + string + "]"); byte[] expected = JSSUtil.encode(tag, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testDecodingEmptyString() throws Exception { String input = ""; byte[] data = JSSUtil.encode(tag, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: [" + input + "]"); String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + output + "]"); Assert.assertEquals(input, output); } @Test public void testEncodingNullCharacters() throws Exception { String string = StringTestUtil.NULL_CHARS; System.out.println("Encoding: [" + StringTestUtil.toString(string.getBytes()) + "]"); byte[] expected = JSSUtil.encode(tag, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); actual = StringTestUtil.normalizeUnicode(actual); System.out.println(" - norm. : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testDecodingNullCharacters() throws Exception { String input = StringTestUtil.NULL_CHARS; byte[] data = JSSUtil.encode(tag, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: [" + StringTestUtil.toString(input.getBytes()) + "]"); String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + StringTestUtil.toString(output.getBytes()) + "]"); Assert.assertEquals(input, output); } @Test public void testEncodingPrintableCharacters() throws Exception { String string = StringTestUtil.PRINTABLE_CHARS; System.out.println("Encoding: [" + string + "]"); byte[] expected = JSSUtil.encode(tag, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testDecodingPrintableCharacters() throws Exception { String input = StringTestUtil.PRINTABLE_CHARS; byte[] data = JSSUtil.encode(tag, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: [" + input + "]"); String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + output + "]"); Assert.assertEquals(input, output); } @Test public void testEncodingNonPrintableCharacters() throws Exception { String string = StringTestUtil.NON_PRINTABLE_CHARS; System.out.println("Encoding: [" + string + "]"); byte[] expected = JSSUtil.encode(tag, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testDecodingNonPrintableCharacters() throws Exception { String input = StringTestUtil.NON_PRINTABLE_CHARS; byte[] data = JSSUtil.encode(tag, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: [" + input + "]"); String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + output + "]"); Assert.assertEquals(input, output); } @Test public void testEncodingControlCharacters() throws Exception { String string = StringTestUtil.CONTROL_CHARS; System.out.println("Encoding: [" + StringTestUtil.toString(string.getBytes()) + "]"); byte[] expected = JSSUtil.encode(tag, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testDecodingControlCharacters() throws Exception { String input = StringTestUtil.CONTROL_CHARS; byte[] data = JSSUtil.encode(tag, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: [" + StringTestUtil.toString(input.getBytes()) + "]"); String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + StringTestUtil.toString(output.getBytes()) + "]"); Assert.assertEquals(input, output); } @Test public void testEncodingMultibyteCharacters() throws Exception { String string = StringTestUtil.MULTIBYTE_CHARS; System.out.println("Encoding: [" + string + "]"); System.out.println(" - expected: IOException"); try { byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.fail(); } catch (Exception e) { System.out.println(" - actual : " + e.getClass().getSimpleName()); Assert.assertTrue(e instanceof IOException); } } @Test public void testDecodingMultibyteCharacters() throws Exception { String input = StringTestUtil.MULTIBYTE_CHARS; byte[] data = JSSUtil.encode(DerValue.tag_UTF8String, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: IOException"); try { String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + StringTestUtil.toString(output.getBytes()) + "]"); Assert.fail(); } catch (Exception e) { System.out.println(" - actual : " + e.getClass().getSimpleName()); Assert.assertTrue(e instanceof IOException); } } @Test public void testEncodingTime() throws Exception { System.out.println("Encoding time:"); String string = StringTestUtil.NULL_CHARS + StringTestUtil.PRINTABLE_CHARS + StringTestUtil.NON_PRINTABLE_CHARS + StringTestUtil.CONTROL_CHARS; long t0 = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) JSSUtil.encode(tag, string); long t1 = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) StringTestUtil.encode(tag, string); long t2 = System.currentTimeMillis(); long time1 = t1 - t0; long time2 = t2 - t1; System.out.println(" - JSS : " + time1 + " ms"); System.out.println(" - Internal: " + time2 + " ms"); } @Test public void testDecodingTime() throws Exception { System.out.println("Decoding time:"); String string = StringTestUtil.NULL_CHARS + StringTestUtil.PRINTABLE_CHARS + StringTestUtil.NON_PRINTABLE_CHARS + StringTestUtil.CONTROL_CHARS; byte[] data = JSSUtil.encode(tag, string); long t0 = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) JSSUtil.decode(tag, data); long t1 = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) StringTestUtil.decode(tag, data); long t2 = System.currentTimeMillis(); long time1 = t1 - t0; long time2 = t2 - t1; System.out.println(" - JSS : " + time1 + " ms"); System.out.println(" - Internal: " + time2 + " ms"); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/JCAKeyWrap.java000077500000000000000000000413541412550063600237600ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.io.IOException; import java.io.UnsupportedEncodingException; import org.mozilla.jss.crypto.SecretKeyFacade; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.Policy; import org.mozilla.jss.crypto.TokenException; import javax.crypto.SecretKey; import javax.crypto.BadPaddingException; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.KeyGenerator; import javax.crypto.NoSuchPaddingException; import java.security.AlgorithmParameters; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.Provider; import java.security.SecureRandom; import java.security.Security; import java.util.Arrays; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.util.IncorrectPasswordException; import org.mozilla.jss.util.PasswordCallback; /** * Test Mozilla-JSS provider key wrap/unwrap * * JSS currently needs to compile with JDK 1.4.2.x * * This program tests wrapping/unwrapping on symmetric keys. * unwraping of private keys is not available at this time see * https://bugzilla.mozilla.org/show_bug.cgi?id=135328 * */ public class JCAKeyWrap { protected static final String MOZ_PROVIDER_NAME = "Mozilla-JSS"; public static void main(String args[]) { if (args.length != 2) { usage(); System.exit(1); } String dbdir = args[0]; String passwdfile = args[1]; try { JCAKeyWrap keyWrap = new JCAKeyWrap(dbdir, passwdfile); //If the IBMJCE provider exists tests with it otherwise //use the SunJCE provider. String otherProvider = new String("IBMJCE"); String otherRSAProvider = new String("IBMJCE"); Provider p = null; p = Security.getProvider(otherProvider); if (p == null) { otherProvider = new String("SunJCE"); otherRSAProvider = new String("SunRsaSign"); p = Security.getProvider(otherProvider); if (p == null) { System.out.println("unable to find IBMJCE or SunJCE " + "providers"); Provider[] providers = Security.getProviders(); for (int i = 0; i < providers.length; i++) { System.out.println("Provider " + i + ": " + providers[i].getName()); } System.exit(1); } } // Generate an RSA keypair KeyPairGenerator kpgen; kpgen = KeyPairGenerator.getInstance("RSA", MOZ_PROVIDER_NAME); kpgen.initialize(Policy.RSA_MINIMUM_KEY_SIZE); KeyPair rsaKeyPairNSS = kpgen.generateKeyPair(); kpgen = KeyPairGenerator.getInstance("RSA", otherRSAProvider); kpgen.initialize(Policy.RSA_MINIMUM_KEY_SIZE); KeyPair rsaKeyPairOtherProvider = kpgen.generateKeyPair(); javax.crypto.SecretKey tripleDESKey; KeyGenerator keyGen = KeyGenerator.getInstance("DESede", MOZ_PROVIDER_NAME); tripleDESKey = keyGen.generateKey(); keyWrap.wrapSymetricKeyWithRSA(tripleDESKey, rsaKeyPairNSS, MOZ_PROVIDER_NAME, MOZ_PROVIDER_NAME); if (!keyWrap.isBFipsMode()) { keyWrap.wrapSymetricKeyWithRSA(tripleDESKey, rsaKeyPairNSS, MOZ_PROVIDER_NAME, otherProvider); } keyGen = KeyGenerator.getInstance("AES", MOZ_PROVIDER_NAME); javax.crypto.SecretKey aesKeyToWrap; keyGen.init(128); aesKeyToWrap = keyGen.generateKey(); keyGen = KeyGenerator.getInstance("AES", MOZ_PROVIDER_NAME); int AESKeySize[] = {128, 192, 256}; for (int k = 0; k < AESKeySize.length; k++) { //create AES key javax.crypto.SecretKey aesKey; keyGen.init(AESKeySize[k]); aesKey = keyGen.generateKey(); keyGen = KeyGenerator.getInstance("AES", MOZ_PROVIDER_NAME); int keyStrength = (((SecretKeyFacade) aesKey).key.getStrength()); //JDK 1.4 and 1.5 only supports 128 keys for AES //therefore only do comparison testing of providers with //128 key strength if (keyStrength == 128 && !keyWrap.isBFipsMode()) { keyWrap.wrapSymetricKey(tripleDESKey, "AES/CBC/PKCS5Padding", aesKey, MOZ_PROVIDER_NAME, otherProvider); keyWrap.wrapSymetricKey(aesKeyToWrap, "AES/CBC/PKCS5Padding", aesKey, MOZ_PROVIDER_NAME, otherProvider); keyWrap.wrapSymetricKeyWithRSA(aesKey, rsaKeyPairNSS, MOZ_PROVIDER_NAME, otherProvider); } else { keyWrap.wrapSymetricKey(tripleDESKey, "AES/CBC/PKCS5Padding", aesKey); keyWrap.wrapSymetricKey(aesKeyToWrap, "AES/CBC/PKCS5Padding", aesKey); keyWrap.wrapSymetricKeyWithRSA(aesKey, rsaKeyPairNSS); } aesKeyToWrap = aesKey; } } catch (Exception e) { e.printStackTrace(); System.exit(1); } System.exit(0); } /** * */ public static void usage() { System.out.println( "Usage: java org.mozilla.jss.tests.JCAKeyWrap " + " "); } protected boolean bFipsMode = false; protected byte[] plainText = "Firefox rules!Firefox rules!Firefox rules!Firefox rules!Firefox rules!".getBytes(); protected byte[] plainTextPad = "Thunderbird rules!Thunderbird rules!Thunderbird rules!Thunderbird rules!Thunderbird rules!".getBytes(); /** * Default constructor to initialize Mozilla-JSS * @param certDbLoc * @param passwdFile */ public JCAKeyWrap(String certDbLoc, String passwdFile) { try { CryptoManager cm = CryptoManager.getInstance(); CryptoToken token = cm.getInternalKeyStorageToken(); PasswordCallback cb = new FilePasswordCallback(passwdFile); token.login(cb); if (cm.FIPSEnabled()) { bFipsMode = true; System.out.println("in Fipsmode."); } } catch (IOException ex) { ex.printStackTrace(); System.exit(1); } catch (IncorrectPasswordException ex) { ex.printStackTrace(); System.exit(1); } catch (TokenException ex) { ex.printStackTrace(); System.exit(1); } catch (NotInitializedException ex) { ex.printStackTrace(); System.exit(1); } } /** * * @return true when in FIPS mode false otherwise */ public boolean isBFipsMode() { return bFipsMode; } /** * Randomly selects a cipher transformation "algorithm/mode/padding". * @param symKeyType * @return a cipher transformation "algorithm/mode/padding" * @throws Exception */ public String testCipher(String symKeyType) throws Exception { String testCipher; String[] cipherDESede = {"DESede/ECB/NoPadding", "DESede/CBC/PKCS5Padding", "DESede/CBC/NoPadding"}; String[] cipherAES = {"AES/ECB/NoPadding", "AES/CBC/NoPadding", "AES/CBC/PKCS5Padding"}; SecureRandom r = SecureRandom.getInstance("pkcs11prng", MOZ_PROVIDER_NAME); if (symKeyType.equalsIgnoreCase("AES")) { return cipherAES[r.nextInt(cipherAES.length)]; } else if (symKeyType.equalsIgnoreCase("DESede")) { return cipherDESede[r.nextInt(cipherDESede.length)]; } else { throw new Exception("no support for " + symKeyType); } } /** * * both providers are Mozilla-JSS * * @param symKey * @param keyPair * @throws Exception */ public void wrapSymetricKeyWithRSA(Key symKey, KeyPair keyPair) throws Exception { wrapSymetricKeyWithRSA(symKey, keyPair, MOZ_PROVIDER_NAME, MOZ_PROVIDER_NAME); } /** * * @param symKey * @param keyPair * @param providerA * @param providerB * @throws Exception */ public void wrapSymetricKeyWithRSA( Key symKey, KeyPair keyPair, String providerA, String providerB) throws Exception { try { String symKeyType = new String(symKey.getAlgorithm()); System.out.print("Wrap " + symKeyType + " " + ((SecretKeyFacade) symKey).key.getStrength() + " with RSA. "); // wrap key Cipher cipher = Cipher.getInstance("RSA", providerA); cipher.init(Cipher.WRAP_MODE, keyPair.getPublic()); byte[] wrappedData = cipher.wrap(symKey); // unwrap key cipher = Cipher.getInstance("RSA", providerA); cipher.init(Cipher.UNWRAP_MODE, keyPair.getPrivate()); SecretKey unwrappedKey = (javax.crypto.SecretKey) cipher.unwrap(wrappedData, symKeyType, Cipher.SECRET_KEY); testKeys(symKey, unwrappedKey, providerA, providerB); } catch (BadPaddingException ex) { ex.printStackTrace(); System.exit(1); } catch (UnsupportedEncodingException ex) { ex.printStackTrace(); System.exit(1); } catch (IllegalBlockSizeException ex) { ex.printStackTrace(); System.exit(1); } catch (InvalidKeyException ex) { ex.printStackTrace(); System.exit(1); } catch (NoSuchAlgorithmException ex) { ex.printStackTrace(); System.exit(1); } catch (NoSuchPaddingException ex) { ex.printStackTrace(); System.exit(1); } } /** * both providers used will be Mozilla-JSS * * @param symKey * @param wrapperAlg * @param wrapperKey * @throws Exception */ public void wrapSymetricKey(Key symKey, String wrapperAlg, Key wrapperKey) throws Exception { wrapSymetricKey(symKey, wrapperAlg, wrapperKey, MOZ_PROVIDER_NAME, MOZ_PROVIDER_NAME); } /** * compare two keys * * @param key1 * @param key2 * @return true if equal false otherwise */ static boolean keysEqual(Key key1, Key key2) { if (key1.equals(key2)) { return true; } if (Arrays.equals(key1.getEncoded(), key2.getEncoded())) { return true; } return false; } /** * * @param keyA * @param keyB * @param providerA * @param providerB * @throws java.lang.Exception */ protected void testKeys(Key keyA, Key keyB, String providerA, String providerB) throws Exception { //ensure keys are equal if (bFipsMode) { //bFipsMode providerA and providerB mozilla-JSS //Keys are not extractable so just check key length if (((SecretKeyFacade) keyA).key.getStrength() != ((SecretKeyFacade) keyB).key.getStrength()) { throw new Exception("unwrapped key strength does not " + "match orginal"); } } else if (!keysEqual(keyA, keyB)) { throw new Exception("unwrapped key " + "does not match original"); } //As an extra test encrypt with keyA using ProviderA //and decrypt with with keyB using ProviderB String cipherAlg = testCipher(keyA.getAlgorithm()); System.out.println("Test " + cipherAlg + " encrypt with " + providerA + " decrypt " + providerB); // if no padding is used plainText needs to be fixed length // block divisable by 8 bytes byte[] plaintext = plainText; if (cipherAlg.endsWith("PKCS5Padding")) { plaintext = plainTextPad; } //encrypt some text as a test with the key to be wrap Cipher cipher = Cipher.getInstance(cipherAlg, providerA); cipher.init(Cipher.ENCRYPT_MODE, keyA); byte[] encryptedText = cipher.doFinal(plaintext); //generate the algorithm Parameters; they need to be //the same for encrypt/decrypt if they are needed. AlgorithmParameters ap = null; byte[] encodedAlgParams = null; ap = cipher.getParameters(); if (ap != null) { //get parameters to store away as example. encodedAlgParams = ap.getEncoded(); } // use the unwrapped key for decryption cipher = Cipher.getInstance(cipherAlg, providerB); if (encodedAlgParams == null) { cipher.init(Cipher.DECRYPT_MODE, keyB); } else { //retrieve the algorithmParameters from the encoded array AlgorithmParameters aps = AlgorithmParameters.getInstance(keyB.getAlgorithm()); aps.init(encodedAlgParams); cipher.init(Cipher.DECRYPT_MODE, keyB, aps); } byte[] recovered = new byte[plaintext.length]; int rLen = cipher.update(encryptedText, 0, encryptedText.length, recovered, 0); rLen += cipher.doFinal(recovered, rLen); if (!java.util.Arrays.equals(plaintext, recovered)) { throw new Exception("key do not match. unable to encrypt/decrypt."); } } /** * * @param symKey * @param wrapperAlg * @param wrapperKey * @param providerA * @param providerB * @throws Exception */ public void wrapSymetricKey(Key symKey, String wrapperAlg, Key wrapperKey, String providerA, String providerB) throws Exception { try { System.out.print("Wrap " + symKey.getAlgorithm() + " " + ((SecretKeyFacade) symKey).key.getStrength() + " with " + wrapperKey.getAlgorithm() + " " + ((SecretKeyFacade) wrapperKey).key.getStrength() + " symmetric key. "); // wrap key Cipher cipher = Cipher.getInstance(wrapperAlg, providerA); cipher.init(Cipher.WRAP_MODE, wrapperKey); byte[] wrappedData = cipher.wrap(symKey); //generate the algorithm Parameters; they need to be //the same for encrypt/decrypt if they are needed. byte[] encodedKeyWrapAP = null; AlgorithmParameters ap = null; ap = cipher.getParameters(); if (ap != null) { //get parameters to store away as example. encodedKeyWrapAP = ap.getEncoded(); } // unwrap key cipher = Cipher.getInstance(wrapperAlg, providerA); if (encodedKeyWrapAP == null) { cipher.init(Cipher.UNWRAP_MODE, wrapperKey); } else { //retrieve the algorithmParameters from the encoded array AlgorithmParameters aps = AlgorithmParameters.getInstance( wrapperKey.getAlgorithm()); aps.init(encodedKeyWrapAP); cipher.init(Cipher.UNWRAP_MODE, wrapperKey, aps); } SecretKey unwrappedKey = (SecretKey) cipher.unwrap(wrappedData, symKey.getAlgorithm(), Cipher.SECRET_KEY); testKeys(symKey, unwrappedKey, providerA, providerB); } catch (BadPaddingException ex) { ex.printStackTrace(); System.exit(1); } catch (IllegalBlockSizeException ex) { ex.printStackTrace(); System.exit(1); } catch (UnsupportedEncodingException ex) { ex.printStackTrace(); System.exit(1); } catch (InvalidKeyException ex) { ex.printStackTrace(); System.exit(1); } catch (NoSuchAlgorithmException ex) { ex.printStackTrace(); System.exit(1); } catch (NoSuchPaddingException ex) { ex.printStackTrace(); System.exit(1); } } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/JCASigTest.java000066400000000000000000000111201412550063600237410ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.Provider; import java.security.Security; import java.security.Signature; import java.security.spec.MGF1ParameterSpec; import java.security.spec.PSSParameterSpec; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.crypto.Policy; public class JCASigTest { public static void usage() { System.out.println( "Usage: java org.mozilla.jss.tests.JCASigTest "); } public static void sigTest(String alg, KeyPair keyPair) throws Exception { byte[] data = new byte[] {1,2,3,4,5,6,7,8,9}; byte[] signature; Signature signer; signer = Signature.getInstance(alg); if (alg.equals("RSASSA-PSS")) { //Set some params, go for SHA256 version. signer.setParameter(new PSSParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-256"), 32, 1)); } System.out.println("Created a signing context"); Provider provider = signer.getProvider(); System.out.println("The provider used for the signer " + provider.getName() + " and the algorithm was " + alg); if (provider.getName().equalsIgnoreCase("Mozilla-JSS") == false) { System.out.println("Mozilla-JSS is supposed to be the " + "default provider for JCASigTest"); System.exit(1); } signer.initSign(keyPair.getPrivate()); System.out.println("initialized the signing operation"); signer.update(data); System.out.println("updated signature with data"); signature = signer.sign(); System.out.println("Successfully signed!"); signer.initVerify(keyPair.getPublic()); System.out.println("initialized verification"); signer.update(data); System.out.println("updated verification with data"); if (signer.verify(signature)) { System.out.println("Signature Verified Successfully!"); } else { System.out.println("ERROR: Signature failed to verify."); } } public static void main(String args[]) throws Exception { CryptoManager manager; KeyPairGenerator kpgen; KeyPair keyPair; if ( args.length != 2 ) { usage(); System.exit(1); } String dbdir = args[0]; String file = args[1]; manager = CryptoManager.getInstance(); manager.setPasswordCallback( new FilePasswordCallback(file) ); Provider[] providers = Security.getProviders(); for ( int i=0; i < providers.length; i++ ) { System.out.println("Provider "+i+": "+providers[i].getName()); } // Generate an RSA keypair kpgen = KeyPairGenerator.getInstance("RSA"); kpgen.initialize(Policy.RSA_MINIMUM_KEY_SIZE); keyPair = kpgen.generateKeyPair(); Provider provider = kpgen.getProvider(); System.out.println("The provider used to Generate the Keys was " + provider.getName() ); System.out.println("provider info " + provider.getInfo() ); if (provider.getName().equalsIgnoreCase("Mozilla-JSS") == false) { System.out.println("Mozilla-JSS is supposed to be the " + "default provider for JCASigTest"); System.exit(1); } sigTest("SHA-256/RSA", keyPair); sigTest("SHA-384/RSA", keyPair); sigTest("SHA-512/RSA", keyPair); sigTest("SHA256withRSA/PSS", keyPair); sigTest("SHA384withRSA/PSS", keyPair); sigTest("SHA512withRSA/PSS", keyPair); sigTest("RSASSA-PSS",keyPair); kpgen = KeyPairGenerator.getInstance("EC"); kpgen.initialize(256); keyPair = kpgen.generateKeyPair(); provider = kpgen.getProvider(); System.out.println("The provider used to Generate the Keys was " + provider.getName() ); System.out.println("provider info " + provider.getInfo() ); if (provider.getName().equalsIgnoreCase("Mozilla-JSS") == false) { System.out.println("Mozilla-JSS is supposed to be the " + "default provider for JCASigTest"); System.exit(1); } sigTest("SHA-256/EC", keyPair); sigTest("SHA-384/EC", keyPair); sigTest("SHA-512/EC", keyPair); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/JCASymKeyGen.java000066400000000000000000000504721412550063600242470ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.io.IOException; import java.security.AlgorithmParameters; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.Provider; import java.security.SecureRandom; import java.security.Security; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.RC2ParameterSpec; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.util.IncorrectPasswordException; import org.mozilla.jss.util.PasswordCallback; /** * */ public class JCASymKeyGen { static final String MOZ_PROVIDER_NAME = "Mozilla-JSS"; byte[] plainText = "Firefox rules!Firefox rules!Firefox rules!Firefox rules!Firefox rules!".getBytes(); byte[] plainTextPad = "Thunderbird rules!Thunderbird rules!Thunderbird rules!Thunderbird rules!Thunderbird rules!".getBytes(); byte[] plainTextB = "NSPR NSS JSS!NSPR NSS JSS!NSPR NSS JSS!".getBytes(); byte[] plainTextPadB = "Use Firefox and Thunderbird!".getBytes(); static boolean bFipsMode = false; /** * Default constructor */ public JCASymKeyGen( String certDbLoc, String passwdFile) { try { CryptoManager cm = CryptoManager.getInstance(); CryptoToken token = cm.getInternalCryptoToken(); if (cm.FIPSEnabled()) { try { bFipsMode=true; PasswordCallback cb = new FilePasswordCallback(passwdFile); token.login(cb); System.out.println("Logged in"); } catch (IncorrectPasswordException ex) { ex.printStackTrace(); System.exit(1); } catch (TokenException ex) { ex.printStackTrace(); System.exit(1); } catch (IOException ex) { ex.printStackTrace(); System.exit(1); } } } catch (NotInitializedException ex) { ex.printStackTrace(); System.exit(1); } } /** * * @param keyType * @param provider * @return javax.crypto.SecretKey key */ public javax.crypto.SecretKey genSecretKey(String keyType, String provider){ javax.crypto.SecretKey key = null; javax.crypto.KeyGenerator kg = null; try { kg = KeyGenerator.getInstance(keyType, provider); if (keyType.equals("AES") || keyType.equals("RC2")) { kg.init(128); //JDK 1.4 and 1.5 only supports 128 keys for AES } System.out.println("Key " + keyType + " generation done by " + kg.getProvider().toString()); key = kg.generateKey(); if( !checkAlgorithm(key, keyType) ) { throw new Exception("Error: " + key.getAlgorithm() + " algorithm"); } //System.out.println("The length of the generated key in bits: " + // (key.getEncoded().length * 8) + // " " + key.getAlgorithm() ); } catch (NoSuchProviderException ex) { ex.printStackTrace(); } catch (NoSuchAlgorithmException ex) { ex.printStackTrace(); } catch (Exception ex) { ex.printStackTrace(); } return key; } /** * * @param keyType * @param provider * @return javax.crypto.SecretKey key */ public javax.crypto.SecretKey genPBESecretKey(String keyType, String provider){ javax.crypto.SecretKey key = null; javax.crypto.SecretKeyFactory kf = null; try { char[] pw = "thunderbird".toCharArray(); byte[] salt = new byte[8]; SecureRandom random = SecureRandom.getInstance("pkcs11prng", MOZ_PROVIDER_NAME); random.nextBytes(salt); int iterationCount = 2; kf = SecretKeyFactory.getInstance(keyType, provider); PBEKeySpec keySpec = new PBEKeySpec(pw, salt, iterationCount); key = kf.generateSecret(keySpec); //todo this should work as well //PBEKeySpec pbeKeySpec = new PBEKeySpec(pw)); // key = kf.generateSecret(pbeKeySpec); System.out.println("Key " + keyType + " generation done by " + kf.getProvider().toString()); if (!bFipsMode) { System.out.println("The length of the generated key in bits: " + (key.getEncoded().length * 8) + " " + key.getAlgorithm() ); } } catch (NoSuchProviderException ex) { ex.printStackTrace(); } catch (NoSuchAlgorithmException ex) { ex.printStackTrace(); } catch (Exception ex) { ex.printStackTrace(); } return key; } /** * * @param sKey * @param algFamily * @param algType * @param providerForEncrypt * @param providerForDecrypt */ public void testCipher(javax.crypto.SecretKey sKey, String algFamily, String algType, String providerForEncrypt, String providerForDecrypt) throws Exception { try { // if no padding is used plainText needs to be fixed length // block divisable by 8 bytes byte[] plaintext = plainText; if (algType.endsWith("PKCS5Padding")) { plaintext = plainTextPad; } //encypt Cipher cipher = Cipher.getInstance(algType, providerForEncrypt); AlgorithmParameters ap = null; byte[] encodedAlgParams = null; AlgorithmParameterSpec RC2ParSpec = null; if (algFamily.compareToIgnoreCase("RC2")==0) { //JDK 1.4 requires you to pass in generated algorithm //parameters for RC2 (JDK 1.5 does not). byte[] iv = new byte[8]; SecureRandom random = SecureRandom.getInstance("pkcs11prng", MOZ_PROVIDER_NAME); random.nextBytes(iv); RC2ParSpec = new RC2ParameterSpec(128, iv); cipher.init(Cipher.ENCRYPT_MODE, sKey, RC2ParSpec); } else { cipher.init(Cipher.ENCRYPT_MODE, sKey); //generate the algorithm Parameters; they need to be //the same for encrypt/decrypt if they are needed. ap = cipher.getParameters(); if (ap != null) { //get parameters to store away as example. encodedAlgParams = ap.getEncoded(); } } //System.out.print(plaintext.length + " plaintext size " + // providerForEncrypt + " encrypt outputsize: " + // cipher.getOutputSize(plaintext.length)); byte[] ciphertext = new byte[cipher.getOutputSize(plaintext.length)]; int cLen = cipher.update(plaintext, 0, plaintext.length, ciphertext, 0); cLen += cipher.doFinal(ciphertext, cLen); //decrypt cipher = Cipher.getInstance(algType, providerForDecrypt); if (encodedAlgParams == null) if (RC2ParSpec != null) // JDK 1.4 RC2 cipher.init(Cipher.DECRYPT_MODE, sKey, RC2ParSpec); else cipher.init(Cipher.DECRYPT_MODE, sKey); else { //retrieve the algorithmParameters from the encoded array AlgorithmParameters aps = AlgorithmParameters.getInstance(algFamily); aps.init(encodedAlgParams); cipher.init(Cipher.DECRYPT_MODE, sKey, aps); } byte[] recovered = new byte[cLen]; int rLen = cipher.update(ciphertext, 0, cLen, recovered, 0); rLen += cipher.doFinal(recovered, rLen); //ensure the recovered bytes equals the orginal plaintext boolean isEqual = true; for (int i = 0; i < plaintext.length; i++) { if (plaintext[i] != recovered[i]) { isEqual = false; break; } } if (isEqual) { //System.out.println(providerForEncrypt + " encrypted & " + // providerForDecrypt + " decrypted using " + // algType + " successful."); } else { throw new Exception("ERROR: " + providerForEncrypt + " and " + providerForDecrypt + " failed for " + algType ); } } catch (InvalidKeyException ex) { ex.printStackTrace(); } catch (javax.crypto.BadPaddingException ex) { ex.printStackTrace(); } catch (NoSuchProviderException ex) { ex.printStackTrace(); } catch (javax.crypto.NoSuchPaddingException ex) { ex.printStackTrace(); } catch (javax.crypto.IllegalBlockSizeException ex) { ex.printStackTrace(); } catch (NoSuchAlgorithmException ex) { ex.printStackTrace(); } } /** * * @param sKey * @param algFamily * @param algType * @param providerForEncrypt * @param providerForDecrypt */ public void testMultiPartCipher(javax.crypto.SecretKey sKey, String algFamily, String algType, String providerForEncrypt, String providerForDecrypt) throws Exception { try { // if no padding is used plainText needs to be fixed length // block divisable by 8 bytes byte[] plaintext = plainText; byte[] plaintextB = plainTextB; if (algType.endsWith("PKCS5Padding")) { plaintext = plainTextPad; plaintextB = plainTextPadB; } //encypt Cipher cipher = Cipher.getInstance(algType, providerForEncrypt); AlgorithmParameters ap = null; byte[] encodedAlgParams = null; AlgorithmParameterSpec RC2ParSpec = null; if (algFamily.compareToIgnoreCase("RC2")==0) { //JDK 1.4 requires you to pass in generated algorithm //parameters for RC2 (JDK 1.5 does not). byte[] iv = new byte[8]; SecureRandom random = SecureRandom.getInstance("pkcs11prng", MOZ_PROVIDER_NAME); random.nextBytes(iv); RC2ParSpec = new RC2ParameterSpec(128, iv); cipher.init(Cipher.ENCRYPT_MODE, sKey, RC2ParSpec); } else { cipher.init(Cipher.ENCRYPT_MODE, sKey); //generate the algorithm Parameters; they need to be //the same for encrypt/decrypt if they are needed. ap = cipher.getParameters(); if (ap != null) { //get parameters to store away as example. encodedAlgParams = ap.getEncoded(); } } byte[] ciphertext = new byte[(cipher.getOutputSize(plaintext.length + plaintextB.length))]; int cLen = cipher.update(plaintext, 0, plaintext.length, ciphertext, 0); cLen += cipher.update(plaintextB, 0, plaintextB.length, ciphertext, cLen); cLen += cipher.doFinal(ciphertext, cLen); //decrypt cipher = Cipher.getInstance(algType, providerForDecrypt); if (encodedAlgParams == null) if (RC2ParSpec != null) // JDK 1.4 RC2 cipher.init(Cipher.DECRYPT_MODE, sKey, RC2ParSpec); else cipher.init(Cipher.DECRYPT_MODE, sKey); else { //retrieve the algorithmParameters from the encoded array AlgorithmParameters aps = AlgorithmParameters.getInstance(algFamily); aps.init(encodedAlgParams); cipher.init(Cipher.DECRYPT_MODE, sKey, aps); } byte[] recovered = new byte[cLen]; int rLen = cipher.update(ciphertext, 0, cLen, recovered, 0); rLen += cipher.doFinal(recovered, rLen); //ensure the recovered bytes equals the original plaintext boolean isEqual = true; for (int i = 0; i < plaintext.length; i++) { if (i [passwordFile]"); System.out.println("password file only required if in " + "FIPSMODE."); System.out.println("FIPSMODE requires Java 1.6 or higher!"); System.exit(1); } //If the IBMJCE provider exists tests with it otherwise //use the SunJCE provider. String otherProvider = new String("IBMJCE"); Provider p = null; p = Security.getProvider(otherProvider); if (p == null) { otherProvider = new String("SunJCE"); p = Security.getProvider(otherProvider); if (p == null){ System.out.println("unable to find IBMJCE or SunJCE providers"); System.exit(1); } } JCASymKeyGen skg = new JCASymKeyGen(certDbLoc, passwdFile); System.out.println(otherProvider + ": " + p.getInfo()); p = Security.getProvider(MOZ_PROVIDER_NAME); System.out.println(MOZ_PROVIDER_NAME + ": " + p.getInfo()); javax.crypto.SecretKey mozKey = null; try { for (int i = 0 ; i < symKeyTable.length; i++) { try { //generate the key using mozilla if (symKeyTable[i][0].startsWith("PBE") == true) { mozKey = skg.genPBESecretKey(symKeyTable[i][0], MOZ_PROVIDER_NAME); } else { mozKey = skg.genSecretKey(symKeyTable[i][0], MOZ_PROVIDER_NAME); } } catch(Exception e) { System.out.println("unable to generate key: " + symKeyTable[i][0] + " " + e.getMessage()); } //test the cipher algorithms for this keyType for (int a = 1 ; a < symKeyTable[i].length; a++){ //encrypt/decrypt with Mozilla Provider skg.testCipher(mozKey, symKeyTable[i][0], symKeyTable[i][a], MOZ_PROVIDER_NAME, MOZ_PROVIDER_NAME); skg.testMultiPartCipher(mozKey, symKeyTable[i][0], symKeyTable[i][a], MOZ_PROVIDER_NAME, MOZ_PROVIDER_NAME); try { //check to see if the otherProvider we are testing //against supports the algorithm. Cipher cipher = Cipher.getInstance(symKeyTable[i][a], otherProvider); } catch (Exception e) { System.out.println(MOZ_PROVIDER_NAME + " only supports " + symKeyTable[i][a]); //therefore don't try comparison continue; } //in FIPSMODE you can only use the Mozilla Provider if (!bFipsMode) { //encrypt with Mozilla, and Decrypt with otherProvider skg.testCipher(mozKey, symKeyTable[i][0], symKeyTable[i][a], MOZ_PROVIDER_NAME, otherProvider); skg.testMultiPartCipher(mozKey, symKeyTable[i][0], symKeyTable[i][a], MOZ_PROVIDER_NAME, otherProvider); //encrypt with otherProvider and decrypt with Mozilla skg.testCipher(mozKey, symKeyTable[i][0], symKeyTable[i][a], otherProvider, MOZ_PROVIDER_NAME); skg.testMultiPartCipher(mozKey, symKeyTable[i][0], symKeyTable[i][a], otherProvider, MOZ_PROVIDER_NAME); System.out.println(MOZ_PROVIDER_NAME + " and " + otherProvider + " tested " + symKeyTable[i][a]); } } } } catch(Exception e) { e.printStackTrace(); System.exit(1); } //end of main System.exit(0); } /** * Validate if the key algorithm of a given SecretKey * is the same as expected. * @param SecretKey k * @param String algorithm * @return boolean status */ private boolean checkAlgorithm(SecretKey k, String alg) { boolean status = false; if( k.getAlgorithm().equals(alg) ) { status = true; } return status; } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/JSSE_SSLClient.java000077500000000000000000000454401412550063600245040ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.lang.reflect.InvocationTargetException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchProviderException; import java.util.ArrayList; import java.util.Iterator; import javax.net.ssl.HandshakeCompletedEvent; import javax.net.ssl.HandshakeCompletedListener; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This program connects to any SSL Server to exercise * all ciphers supported by JSSE for a given JDK/JRE * version. The result is listing of common ciphers * between the server and this JSSE client. * */ public class JSSE_SSLClient { public static Logger logger = LoggerFactory.getLogger(JSSE_SSLClient.class); // Local members private String sslRevision = "TLS"; private String host = null; private int port = -1; private String cipherName = null; private String path = null; private int debug_level = 0; private String EOF = "test"; private String keystoreLoc = "rsa.pfx"; private SSLSocketFactory factory = null; /* ciphersuites to test */ private ArrayList ciphersToTest = new ArrayList<>(); /* h_ciphers is for ciphersuite that were able to successfully * connect to the server */ private ArrayList h_ciphers = new ArrayList<>(); /* f_ciphers is for ciphersuite that failed to connect to the server */ private ArrayList f_ciphers = new ArrayList<>(); private boolean bVerbose = false; private boolean bFipsMode = false; /** * Set the protocol type and revision * @param fSslRevision */ public void setSslRevision(String fSslRevision) { if (!(fSslRevision.equals("TLS") || fSslRevision.equals("SSLv3"))) { logger.error("type must equal \'TLS\' or \'SSLv3\'\n"); System.exit(1); } this.sslRevision = fSslRevision; } /** * Set the host name to connect to. * @param fHost */ public void setHost(String fHost) { this.host = fHost; } /** * Set the port number to connect to. * @param fPort */ public void setPort(int fPort) { this.port = fPort; } /** * Set the cipher suite name to use. * @param fCipherSuite */ public void setCipherSuite(String fCipherSuite) { this.cipherName = fCipherSuite; } /** * Set the location of rsa.pfx * @param fKeystoreLoc */ public void setKeystoreLoc(String fKeystoreLoc) { keystoreLoc = fKeystoreLoc + "/" + keystoreLoc; } /** * Get the location of rsa.pfx * @return String fKeystoreLoc */ public String getKeystoreLoc() { return keystoreLoc; } /** * Default constructor. */ public JSSE_SSLClient() { //Do nothing. } public boolean isServerAlive() { boolean isServerAlive = false; SSLSocket socket = null; if (factory == null) { initSocketFactory(); } for (int i = 0 ; i < 20 ; i++) { try { Thread.sleep(1000); logger.info("Testing Connection:" + host + ":" + port); socket = (SSLSocket)factory.createSocket(host, port); socket.setEnabledCipherSuites(factory.getDefaultCipherSuites()); if (socket.isBound()) { logger.info("connect isBound"); isServerAlive = true; socket.close(); break; } } catch (java.net.ConnectException ex) { //not able to connect } catch (InterruptedException ex) { ex.printStackTrace(); } catch (IOException ex) { ex.printStackTrace(); } } return isServerAlive; } /** * Test communication with SSL server S */ public void testCiphersuites() { SSLSocket socket = null; int i = 0; if (factory == null) { initSocketFactory(); } if (!isServerAlive()) { logger.error("Unable to connect to " + host + ":" + port + " exiting."); System.exit(1); } Iterator iter = ciphersToTest.iterator(); while (iter.hasNext()) { String cs = iter.next(); String ciphers[] = {cs}; try { socket = (SSLSocket)factory.createSocket(host, port); socket.setEnabledCipherSuites(ciphers); testSSLSocket(socket, cs, i++); } catch (Exception ex) { logger.warn("failed ciphersuite" + ciphers[0]); f_ciphers.add(ciphers[0]); } } } public void configureCipherSuites(String server, String CipherSuite) { boolean testCipher = true; if (factory == null) { initSocketFactory(); } String ciphers[] = factory.getSupportedCipherSuites(); for (int i = 0; i < ciphers.length; ++i) { String ciphersuite = ciphers[i]; testCipher = true; if (bVerbose) { System.out.print(ciphersuite); } if (server.equalsIgnoreCase("JSS")) { //For JSS SSLServer don't test if ((ciphersuite.indexOf("_DHE_") != -1)|| (ciphersuite.indexOf("_DES40_") != -1) || (ciphersuite.indexOf("TLS_EMPTY_RENEGOTIATION_INFO_SCSV") != -1) || (ciphersuite.indexOf("SHA256") != -1) || // reenable in bug 776597 (ciphersuite.indexOf("_anon_") != -1) || (ciphersuite.indexOf("_KRB5_") != -1)) { if (bVerbose) System.out.print(" -"); testCipher = false; } } if (server.equalsIgnoreCase("JSSE")) { //For JSSE SSLServers don't test _DHE_, _EXPORT_, _anon_, _KRB5_ /* if ((ciphersuite.indexOf("_DHE_") != -1) || (ciphersuite.indexOf("_EXPORT_") != -1) || (ciphersuite.indexOf("_anon_") != -1) || (ciphersuite.indexOf("_KRB5_") != -1) ) { if (bVerbose) System.out.print(" -"); testCipher = false; } */ } if (testCipher) { ciphersToTest.add(ciphers[i]); if (bVerbose) System.out.print(" - Testing"); } } if (bVerbose) System.out.print("\n"); if(bVerbose) System.out.println("\nTesting " + ciphersToTest.size() + " ciphersuites."); } private void initSocketFactory() { SSLContext ctx = null; KeyManagerFactory kmf = null; TrustManagerFactory tmf = null; KeyStore ks = null; KeyStore ksTrust = null; String provider = "SunJCE"; /* * Set up a key manager for client authentication * if asked by the server. Use the implementation's * default TrustStore and secureRandom routines. */ char[] passphrase = "m1oZilla".toCharArray(); try { String javaVendor = System.getProperty("java.vendor"); logger.debug("JSSE_SSLClient: java.vendor: " + javaVendor); // Initialize the system if (javaVendor.equals("IBM Corporation")) { System.setProperty("java.protocol.handler.pkgs", "com.ibm.net.ssl.www.protocol.Handler"); java.security.Security.addProvider((java.security.Provider) Class.forName("com.ibm.jsse2.IBMJSSEProvider2").getConstructor().newInstance()); provider = "IBMJCE"; } else { System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol"); java.security.Security.addProvider((java.security.Provider) Class.forName("com.sun.crypto.provider.SunJCE").getConstructor().newInstance()); } // Load the keystore that contains the certificate String certificate = new String("SunX509"); ks = KeyStore.getInstance("PKCS12"); if (javaVendor.equals("IBM Corporation")) { certificate = new String("IbmX509"); ks = KeyStore.getInstance("PKCS12", provider); } try { kmf = KeyManagerFactory.getInstance(certificate); try (FileInputStream in = new FileInputStream(getKeystoreLoc())) { ks.load(in, passphrase); } } catch (Exception keyEx) { if (System.getProperty("java.vendor").equals("IBM Corporation")) { logger.error("Using IBM JDK: Cannot load keystore due "+ "to strong security encryption settings\nwith limited " + "Jurisdiction policy files :\n" + "http://www-1.ibm.com/support/docview.wss?uid=swg21169931"); System.exit(0); } else { logger.error(keyEx.getMessage(), keyEx); } throw keyEx; } kmf.init(ks, passphrase); // trust manager that trusts all certificates TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } @Override public void checkClientTrusted( java.security.cert.X509Certificate[] chain, String authType) {} @Override public void checkServerTrusted( java.security.cert.X509Certificate[] chain, String authType) {} } }; ctx = SSLContext.getInstance(sslRevision); ctx.init(kmf.getKeyManagers(), trustAllCerts, null); factory = ctx.getSocketFactory(); String[] JSSE_ciphers = factory.getSupportedCipherSuites(); } catch (KeyStoreException ex) { ex.printStackTrace(); } catch (NoSuchProviderException ex) { ex.printStackTrace(); } catch (ClassNotFoundException ex) { ex.printStackTrace(); } catch (IllegalAccessException ex) { ex.printStackTrace(); } catch (InstantiationException ex) { ex.printStackTrace(); } catch (NoSuchMethodException ex) { ex.printStackTrace(); } catch (InvocationTargetException ex) { ex.printStackTrace(); } catch (Exception ex) { ex.printStackTrace(); } } /** * sendServerShutdownMsg */ public void sendServerShutdownMsg() { try { SSLSocket socket = null; if (factory == null) { initSocketFactory(); } socket = (SSLSocket)factory.createSocket(host, port); socket.setEnabledCipherSuites(factory.getDefaultCipherSuites()); if (bVerbose) { logger.info("Sending shutdown message to server."); } socket.startHandshake(); OutputStream os = socket.getOutputStream(); PrintWriter out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(os))); out.println("shutdown"); out.flush(); out.close(); socket.close(); } catch (Exception ex) { ex.printStackTrace(); } } private void testSSLSocket(SSLSocket socket, String ciphersuite, int socketID) { /* * register a callback for handshaking completion event */ try { socket.addHandshakeCompletedListener( new HandshakeCompletedListener() { @Override public void handshakeCompleted( HandshakeCompletedEvent event) { h_ciphers.add(event.getCipherSuite()); logger.info(event.getCipherSuite()); logger.info("SessionId " + event.getSession() + " Test Status : PASS"); } } ); } catch (Exception handshakeEx) { logger.error(handshakeEx.getMessage(), handshakeEx); System.exit(1); } try { // Set socket timeout to 10 sec socket.setSoTimeout(10 * 1000); socket.startHandshake(); String outputLine = null; String inputLine = null; InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); BufferedReader bir = new BufferedReader( new InputStreamReader(is)); PrintWriter out; out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(os))); //write then read on the connection once. outputLine = ciphersuite + ":" + socketID + "\n"; if (bVerbose) { logger.info("Sending: " + outputLine); } out.print(outputLine); out.flush(); inputLine = bir.readLine(); if (bVerbose) { logger.info("Received: " + inputLine + " on Client-" + socketID); } bir.close(); out.close(); } catch (SSLHandshakeException ex) { f_ciphers.add(ciphersuite); } catch (IOException ex) { logger.error(ex.getMessage(), ex); System.exit(1); } try { socket.close(); } catch (IOException ex) { ex.printStackTrace(); } } public void outputCipherResults() { String banner = new String ("\n----------------------------------------------------------\n"); logger.info(banner); logger.info("JSSE has " + factory.getSupportedCipherSuites().length + " ciphersuites and " + ciphersToTest.size() + " were configured and tested."); if (ciphersToTest.size() == h_ciphers.size()) { logger.info("All " + ciphersToTest.size() + " configured ciphersuites tested Successfully!\n"); } if (!h_ciphers.isEmpty()) { if (!f_ciphers.isEmpty()) { logger.info(banner); logger.info(h_ciphers.size() + " ciphersuites successfully connected to the "+ "server\n"); } Iterator iter = h_ciphers.iterator(); while (iter.hasNext()) { logger.info(iter.next()); } } if (bFipsMode) { logger.info("Note: ciphersuites that have the prefix " + "\"SSL\" or \"SSL3\" were used in TLS mode."); } if (ciphersToTest.size() != (h_ciphers.size() + f_ciphers.size())) { logger.warn("did not test all expected ciphersuites"); } if (!f_ciphers.isEmpty()) { logger.info(banner); logger.info(f_ciphers.size() + " ciphersuites that did not connect to the "+ "server\n\n"); Iterator iter = f_ciphers.iterator(); while (iter.hasNext()) { logger.info(iter.next()); } logger.error("we should have no failed ciphersuites!"); System.exit(1); } logger.info(banner); } /** * Main method for local unit testing. */ public static void main(String [] args) { String testCipher = null; String testHost = "localhost"; String keystoreLocation = "rsa.pfx"; int testPort = 29750; String serverType = "JSSE"; String usage = "java org.mozilla.jss.tests.JSSE_SSLClient" + "\n " + " "; try { if ( args[0].toLowerCase().equals("-h") || args.length < 1) { System.out.println(usage); System.exit(1); } if ( args.length >= 1 ) { keystoreLocation = args[0]; } if ( args.length >= 2) { testPort = Integer.parseInt(args[1]); System.out.println("using port: " + testPort); } if ( args.length >= 3) { testHost = args[2]; } if ( args.length == 4) { serverType = args[3]; } if ( args.length == 5) { testCipher = args[4]; } } catch (Exception e) { System.out.println(usage); System.exit(1); } JSSE_SSLClient sslSock = new JSSE_SSLClient(); sslSock.setHost(testHost); sslSock.setPort(testPort); sslSock.setKeystoreLoc(keystoreLocation); sslSock.setCipherSuite(testCipher); sslSock.configureCipherSuites(serverType, testCipher); try { sslSock.testCiphersuites(); } catch (Exception e) { logger.error("Exception caught testing ciphersuites: " + e.getMessage(), e); System.exit(1); } sslSock.sendServerShutdownMsg(); sslSock.outputCipherResults(); System.exit(0); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/JSSE_SSLServer.java000077500000000000000000000320151412550063600245260ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.Socket; import java.net.SocketTimeoutException; import java.security.KeyStore; import java.security.Provider; import java.security.Security; //note: SunPKCS11 requires JDK 1.5 or higher. //SunPKCS11 import sun.security.pkcs11.SunPKCS11; import java.util.Vector; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLServerSocket; import javax.net.ssl.SSLServerSocketFactory; import org.mozilla.jss.CryptoManager; /** * JSSE SSLServer class that acts as SSL Server * * @author Sandeep.Konchady@Sun.COM * @version 1.0 */ public class JSSE_SSLServer { private int DefaultServerPort = 29753; private int port = DefaultServerPort; private String type = "SSLv3"; private String configDir = ""; private boolean bClientAuth = false; private boolean bVerbose = false; private Vector supportedCiphers = new Vector<>(); private CryptoManager manager; private String provider = "SunJCE"; /** * Constructs a JSSE_SSLServer. */ public JSSE_SSLServer() throws IOException { } /** * Set the provider to use. * @param p */ public void setProvider(String p) { provider = p; } /** * Get the configured provider. * @return String provider */ public String getProvider() { return provider; } /** * Set the location of keystore file. * @param fconfigDir */ public void setKeystore(String fconfigDir) { configDir = fconfigDir; } /** * Get the location of keystore file. * @return String configDir */ public String getKeystore() { return configDir; } /** * Main method to create the class server. This takes * one command line arguments, the port on which the * server accepts requests. */ public static void main(String args[]) { try { (new JSSE_SSLServer()).startSSLServer(args); } catch (Exception e) {} } /** * Start SSLServer and accept connections. * @param args */ public void startSSLServer(String[] args) throws Exception { String configDir = ""; String pwFile = ""; String nssConfig = ""; JSSE_SSLServer sslServer = new JSSE_SSLServer(); if ( args.length <= 1 ) { System.out.println( "USAGE: java JSSE_SSLServer [port] [TLS | SSLv3]" + "[ClientAuth = true | false]" + "[config directory] [keystore filename]" + "[NSS DB passwordFile]" + "[JCE || Mozilla-JSS || Sunpkcs11]"); System.out.println( "\nIf the second argument is TLS, it will start as a\n" + "TLS server, otherwise, it will be started in SSLv3 mode." + "\nIf the third argument is true,it will require\n" + "client authentication as well."); System.exit(1); } for (int i = 0; i < args.length; i++) { System.out.println(i + " = " + args[i]); } if (args.length >= 1) { port = Integer.parseInt(args[0]); } if (args.length >= 2) { type = args[1]; } if (args.length >= 3 && args[2].equals("true")) { bClientAuth = true; } if (args.length >= 4 && args.length >= 5) { configDir = args[3]; String keystore = configDir + "/" + args[4]; if ( keystore != null ) { sslServer.setKeystore(keystore); } } if (args.length >= 7 && args.length >=8 ) { if ((args[5].equalsIgnoreCase("Mozilla-JSS"))) { if (args.length >= 8) { pwFile = args[7]; } System.out.println("Initializing " + args[5]); manager = CryptoManager.getInstance(); manager.setPasswordCallback( new FilePasswordCallback(pwFile) ); } else if (args[5].equalsIgnoreCase("Sunpkcs11")) { System.out.println("Sunpkcs11 requires JDK 1.5" + "at this time JSS need to build with JDK 1.4.2"); //SunPKCS11 nssConfig = args[6]; //SunPKCS11 System.out.println("Initializing " + args[5] + "-NSS"); //SunPKCS11 Provider nss = null; //SunPKCS11 nss = new sun.security.pkcs11.SunPKCS11(nssConfig); //SunPKCS11 Security.insertProviderAt(nss, 1); //SunPKCS11 System.out.println("Initialized " + args[5] + "-NSS"); } else { //use default } } Provider[] providers = Security.getProviders(); for ( int i=0; i < providers.length; i++ ) { System.out.println("Provider "+i+": "+providers[i].getName()); } // System.out.println("using port: " + port); // System.out.println("mode type " + type + " ClientAuth " + // (bClientAuth ? "true" : "false")); // System.out.println("configDir " + configDir); try { System.out.println("creating SSLSockets:"); SSLServerSocketFactory ssf = sslServer.getServerSocketFactory(type); if ( ssf != null ) { SSLServerSocket ss = (SSLServerSocket)ssf.createServerSocket(port); // Set server socket timeout to 5 minutes ss.setSoTimeout(300 * 1000); System.out.println("Enable ciphers."); // Enable all the JSSE ciphersuites ss.setEnabledCipherSuites(ss.getSupportedCipherSuites()); System.out.println("Create JSSE SSLServer"); ss.setNeedClientAuth(bClientAuth); JSSE_SSLServer JSSEServ = new JSSE_SSLServer(); // accept an SSL connection int socketCntr = 0; while (true) { try { //The client will tell the server to shutdown Socket socket = ss.accept(); socket.setSoTimeout(300 * 1000); socketCntr ++; readWriteThread rwThread = new readWriteThread(socket, socketCntr); rwThread.start(); } catch (IOException ex) { System.out.println("Exception caught in " + "SSLServerSocket.accept():" + ex.getMessage()); try { ss.close(); } catch (Exception e) {} break; } } } else { if(System.getProperty("java.vendor").equals("IBM Corporation")){ System.out.println("Using IBM JDK: Cannot load keystore " + "due to strong security encryption settings\nwith " + "limited Jurisdiction policy files :\n http://" + "www-1.ibm.com/support/docview.wss?uid=swg21169931"); System.exit(0); } System.out.println("unable to initialize JSSE_SocketFactory " + "exiting!"); System.exit(1); } } catch (Exception e) { System.out.println("Unable to start JSSE_SSLServer: " + e.getMessage()); e.printStackTrace(); System.exit(1); } System.out.println("Main JSSE_SSLServer exiting."); // Exit gracefully System.exit(0); } /** * ReadWrite thread class that takes a * SSLSocket as input and read then writes * back to client. */ private class readWriteThread extends Thread { private Socket socket = null; private int socketCntr = 0; public readWriteThread(Socket sock, int cntr) { this.socket = sock; this.socketCntr = cntr; } @Override public void run() { try { String inputLine = null; String outputLine = null; InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); BufferedReader bir = new BufferedReader( new InputStreamReader(is)); PrintWriter out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(os))); while (true) { try { if ((inputLine = bir.readLine()) != null) { if (inputLine.equalsIgnoreCase("shutdown")) { if (bVerbose) { System.out.println("Client told " + "JSSE_SSLServer to Shutdown!"); } is.close(); os.close(); socket.close(); System.exit(0); } outputLine = "ServerSSLSocket- " + socketCntr; if (bVerbose) { System.out.println("ServerSSLSocket-" + socketCntr + ": Received " + inputLine); System.out.println("Sending" + outputLine); } out.println(outputLine); out.flush(); } else { /* if you read null then quit. otherwise you * will be in endless loop with the socket * stuck in CLOSED_WAIT. */ if (bVerbose) { System.out.println("ServerSSLSocket-" + socketCntr + " read null aborting connection."); } break; } } catch (SocketTimeoutException ste) { System.out.println("ServerSSLSocket-" + socketCntr + " timed out: " + ste.toString()); break; } catch (IOException ex) { if (bVerbose) ex.printStackTrace(); break; } } /* close streams and close socket */ is.close(); os.close(); socket.close(); if (bVerbose) { System.out.println("ServerSSLSocket " + socketCntr + " has been Closed."); } } catch (IOException e) { e.printStackTrace(); } } } SSLServerSocketFactory getServerSocketFactory(String type) { // set up key manager to do server authentication SSLContext ctx = null; KeyManagerFactory kmf = null; KeyStore ks = null; char[] passphrase = "m1oZilla".toCharArray(); SSLServerSocketFactory ssf = null; System.setProperty("javax.net.ssl.trustStore", System.getProperty("java.home") + "/jre/lib/security/cacerts"); String certificate = "SunX509"; String javaVendor = System.getProperty("java.vendor"); if (javaVendor.equals("IBM Corporation")) certificate = "IbmX509"; System.out.println("keystore loc: " + getKeystore()); if (!(type.equals("TLS") || type.equals("SSLv3"))) { System.out.println("type must equal \'TLS\' or \'SSLv3\'\n"); System.exit(1); } try { ctx = SSLContext.getInstance(type); kmf = KeyManagerFactory.getInstance(certificate); ks = KeyStore.getInstance("PKCS12"); try (FileInputStream in = new FileInputStream(getKeystore())) { ks.load(in, passphrase); } kmf.init(ks, passphrase); ctx.init(kmf.getKeyManagers(), null, null); ssf = ctx.getServerSocketFactory(); return ssf; } catch (Exception e) { //if (Constants.debug_level > 3) e.printStackTrace(); } return ssf; } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/JSSPackageTest.java000066400000000000000000000037471412550063600246340ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; public class JSSPackageTest { public static void main(String[] args) { try { Package pkg = Package.getPackage("org.mozilla.jss"); if (pkg != null) { System.out.println("\n---------------------------------------------------------"); System.out.println("Checking jss jar and library version"); System.out.println("---------------------------------------------------------"); System.out.println(" Introspecting jss jar file"); System.out.println("Package name:\t" + pkg.getName()); System.out.println("Spec title :\t" + pkg.getSpecificationTitle()); System.out.println("Spec vendor :\t" + pkg.getSpecificationVendor()); System.out.println("Spec version:\t" + pkg.getSpecificationVersion()); System.out.println("Impl title :\t" + pkg.getImplementationTitle()); System.out.println("Impl vendor :\t" + pkg.getImplementationVendor()); System.out.println("Impl version:\t" + pkg.getImplementationVersion()); } System.out.println("\n\tFetching version information " + "from CryptoManager"); System.out.println("\n\t" + org.mozilla.jss.CryptoManager.JAR_JSS_VERSION); System.out.println("\n\tTo check the JNI version in libjss.so:"); System.out.println("\n\ttry: strings libjss.so | grep -i header"); System.out.println("\n\tor : ident libjss.so"); System.exit(0); } catch (Exception e) { System.out.println("Exception caught : " + e.getMessage()); e.printStackTrace(); System.exit(1); } } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/JSSProvider.java000066400000000000000000000065651412550063600242340ustar00rootroot00000000000000package org.mozilla.jss.tests; import java.util.*; import java.security.*; import javax.crypto.*; import javax.net.ssl.*; public class JSSProvider { public static String BASE_PACKAGE = "org.mozilla.jss.provider."; public static void shouldProvide(Provider p, String algo, String _type) { String item = (String) p.get(algo); assert(item != null); assert(item.startsWith(BASE_PACKAGE)); assert(item.endsWith("." + _type)); } public static void shouldNotProvide(Provider p, String algo) { assert(p.get(algo) == null); } public static void listProviders() { System.err.println("Providers:"); for (Provider p : Security.getProviders()) { System.err.println(" - " + p); } System.err.println(); } public static void main(String[] args) throws Exception { listProviders(); // Validate that the CryptoManager registers us as the // default/first provider. Provider p = Security.getProvider("Mozilla-JSS"); assert(p != null); assert(p.getName().equals("Mozilla-JSS")); assert(p instanceof org.mozilla.jss.JSSProvider); // Validate assumptions about how provider.get() works: // // Something which by no means should ever be implemented returns // null. shouldNotProvide(p, "Charlie's Chocolate Factory"); // Validate that our provider implements certain interfaces we care // about. In particular, ensure they're overriden as part of our // org.mozilla.jss.provider package, and that the class name matches // what we expect our implementation to be. shouldProvide(p, "KeyManagerFactory.NssX509", "JSSKeyManagerFactory"); // Validate that our provider is "default"; that is, when we get an // algorithm instance without explicitly providing the provider, we // end up with an instance from our provider. Mac m = Mac.getInstance("HmacSHA512"); assert(m.getProvider().getName().equals(p.getName())); // Our KeyManagerFactory and TrustMangerFactory should return KeyManagers // and TrustManagers from our class namespace. KeyManagerFactory kmf = KeyManagerFactory.getInstance("NssX509"); assert(kmf.getKeyManagers().length > 0); for (KeyManager km : kmf.getKeyManagers()) { System.out.println("got KeyManager: " + km); assert(km instanceof org.mozilla.jss.provider.javax.crypto.JSSKeyManager); } TrustManagerFactory tmf = TrustManagerFactory.getInstance("NssX509"); assert(tmf.getTrustManagers().length > 0); for (TrustManager tm : tmf.getTrustManagers()) { System.out.println("got TrustManager: " + tm); assert(tm instanceof org.mozilla.jss.provider.javax.crypto.JSSTrustManager); } // Our KeyStore should return instances or extensions of PK11Cert. KeyStore ks = KeyStore.getInstance("PKCS11"); ks.load(null, null); Enumeration aliases = ks.aliases(); while (aliases.hasMoreElements()) { String alias = aliases.nextElement(); java.security.cert.Certificate cert = ks.getCertificate(alias); if (cert == null) { continue; } assert(cert instanceof org.mozilla.jss.pkcs11.PK11Cert); } } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/JSSUtil.java000066400000000000000000000047301412550063600233470ustar00rootroot00000000000000package org.mozilla.jss.tests; import org.mozilla.jss.asn1.ASN1Template; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.ASN1Value; import org.mozilla.jss.asn1.BMPString; import org.mozilla.jss.asn1.IA5String; import org.mozilla.jss.asn1.PrintableString; import org.mozilla.jss.asn1.Tag; import org.mozilla.jss.asn1.TeletexString; import org.mozilla.jss.asn1.UTF8String; import org.mozilla.jss.asn1.UniversalString; import org.mozilla.jss.netscape.security.util.DerValue; public class JSSUtil { public static byte[] encode(byte tag, String string) throws Exception { ASN1Value value; switch (tag) { case DerValue.tag_BMPString: value = new BMPString(string); break; case DerValue.tag_IA5String: value = new IA5String(string); break; case DerValue.tag_PrintableString: value = new PrintableString(string); break; case DerValue.tag_T61String: value = new TeletexString(string); break; case DerValue.tag_UniversalString: value = new UniversalString(string); break; case DerValue.tag_UTF8String: value = new UTF8String(string); break; default: throw new Exception("Unsupported tag: " + tag); } return ASN1Util.encode(value); } public static String decode(byte tag, byte[] bytes) throws Exception { ASN1Template template; switch (tag) { case DerValue.tag_BMPString: template = new BMPString.Template(); break; case DerValue.tag_IA5String: template = new IA5String.Template(); break; case DerValue.tag_PrintableString: template = new PrintableString.Template(); break; case DerValue.tag_T61String: template = new TeletexString.Template(); break; case DerValue.tag_UniversalString: template = new UniversalString.Template(); break; case DerValue.tag_UTF8String: template = new UTF8String.Template(); break; default: throw new Exception("Unsupported tag: " + tag); } ASN1Value asnValue = ASN1Util.decode(new Tag(Tag.UNIVERSAL, tag), template, bytes); if (asnValue == null) { throw new Exception("Cannot decode the given bytes."); } return asnValue.toString(); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/JSS_FileUploadClient.java000077500000000000000000000307661412550063600257670ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetAddress; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.ssl.SSLCertificateApprovalCallback; import org.mozilla.jss.ssl.SSLClientCertificateSelectionCallback; import org.mozilla.jss.ssl.SSLHandshakeCompletedEvent; import org.mozilla.jss.ssl.SSLHandshakeCompletedListener; import org.mozilla.jss.ssl.SSLSecurityStatus; import org.mozilla.jss.ssl.SSLSocket; import org.mozilla.jss.ssl.TestCertApprovalCallback; import org.mozilla.jss.ssl.TestClientCertificateSelectionCallback; import org.mozilla.jss.util.PasswordCallback; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class JSS_FileUploadClient { public static Logger logger = LoggerFactory.getLogger(JSS_FileUploadClient.class); private String clientCertNick = null; private String serverHost = null; private boolean TestCertCallBack = false; private boolean success = true; private int fCipher = -1; private int port = 29755; private String EOF = "test"; private boolean handshakeCompleted = false; private CryptoManager cm = null; private CryptoToken tok = null; private PasswordCallback cb = null; private String fPasswordFile = "passwords"; private String fCertDbPath = "."; private String fUploadFile = "foo.in"; /** * Default Constructor, do not use. */ public JSS_FileUploadClient() { } /** * Initialize the desired cipher to be set * on the socket. * @param aCipher */ public void setCipher(int aCipher) { fCipher = aCipher; } /** * Initialize the hostname to run the server * @param aHostName */ public void setHostName(String aHostName) { serverHost = aHostName; } /** * Initialize the port to run the server * @param aPort */ public void setPort(int aPort) { port = aPort; } /** * Initialize the passwords file name * @param aPasswordFile */ public void setPasswordFile(String aPasswordFile) { fPasswordFile = aPasswordFile; } /** * Initialize the cert db path name * @param aCertDbPath */ public void setCertDbPath(String aCertDbPath) { fCertDbPath = aCertDbPath; } /** * Initialize the name of the file to * be used for testing along with full path. * @param aUploadFile */ public void setUploadFile(String aUploadFile) { fUploadFile = aUploadFile; } /** * Enable/disable Test Cert Callback. * @param aTestCertCallback */ public void setTestCertCallback(boolean aTestCertCallback) { TestCertCallBack = aTestCertCallback; } /** * Set client certificate * @param aClientCertNick Certificate Nick Name */ public void setClientCertNick(String aClientCertNick) { clientCertNick = aClientCertNick; } /** * Return true if handshake is completed * else return false; * @return boolean handshake status */ public boolean isHandshakeCompleted() { return this.handshakeCompleted; } /** * Set handshakeCompleted flag to indicate * that the socket handshake is coplete. */ public void setHandshakeCompleted() { this.handshakeCompleted = true; } /** * Clear handshakeCompleted flag to indicate * that the system is now ready for another * socket connection. */ public void clearHandshakeCompleted() { this.handshakeCompleted = false; } /** * Set EOF for closing server socket * @param fEof null for closing server socket */ public void setEOF(String fEof) { this.EOF = fEof; } /** * ReadWrite thread class that takes a * SSLSocket as input and sleeps * for 2 sec between sending some test * data and receiving. * NOTE: If bufferedStream.mark(Integer.MAX_VALUE); * method is invoked then fill method of * BufferedInputStream class copies lot of data using * System.arraycopy (which in-turn use memcpy). This * causes very high CPU usage. */ private class readWriteThread extends Thread { private SSLSocket clientSock = null; private int socketCntr = 0; public readWriteThread(SSLSocket sock, int cntr) { clientSock = sock; socketCntr = cntr; } @Override public void run() { try { String socketData = null; char[] cbuf = null; int readLength = 0; String readString = null; OutputStream os = clientSock.getOutputStream(); System.out.println("Reading file foo.in"); BufferedReader in = new BufferedReader( new FileReader(fUploadFile)); System.out.println("Successfully got a handle to " + fUploadFile); PrintWriter out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(os))); while ((readString = in.readLine()) != null) { System.out.println("Read:" + readString); out.println(readString); out.flush(); } in.close(); out.close(); } catch (Exception e) { System.out.println("Exception caught" + e.getMessage()); e.printStackTrace(); System.exit(1); } } } /** * Initialize and create a socket connection to * SSLServer using the set parameters. */ public void doIt() throws Exception { try { cm = CryptoManager.getInstance(); tok = cm.getInternalKeyStorageToken(); cb = new FilePasswordCallback(fPasswordFile); tok.login(cb); } catch (Exception e) { } // connect to the server logger.debug("client about to connect..."); String hostAddr = InetAddress.getByName(serverHost).getHostAddress(); logger.debug("the host " + serverHost + " and the address " + hostAddr); SSLCertificateApprovalCallback approvalCallback = new TestCertApprovalCallback(); SSLClientCertificateSelectionCallback certSelectionCallback = new TestClientCertificateSelectionCallback(); SSLSocket sock = null; if (TestCertCallBack) { logger.debug("calling approvalCallBack"); sock = new SSLSocket(InetAddress.getByName(hostAddr), port, null, 0, new TestCertApprovalCallback(), null); } else { logger.debug("NOT calling approvalCallBack"); sock = new SSLSocket(InetAddress.getByName(hostAddr), port); } logger.debug("clientCertNick=" + clientCertNick); sock.setClientCertNickname(clientCertNick); if ( fCipher != -1 ) { sock.setCipherPreference(fCipher, true); } logger.debug("Client specified cert by nickname"); logger.debug("client connected"); // Set socket timeout to 10 sec //sock.setSoTimeout(10 * 1000); //sock.setKeepAlive(true); sock.addHandshakeCompletedListener( new HandshakeListener("client",this)); sock.forceHandshake(); readWriteThread rwThread = new readWriteThread(sock, 0); rwThread.start(); } /** * SSL Handshake Listener implementation. */ public class HandshakeListener implements SSLHandshakeCompletedListener { private String who; private JSS_FileUploadClient boss; public HandshakeListener(String who, JSS_FileUploadClient boss) { this.who = who; this.boss = boss; } @Override public void handshakeCompleted(SSLHandshakeCompletedEvent event) { try { String mesg = who + " got a completed handshake "; SSLSecurityStatus status = event.getStatus(); if( status.isSecurityOn() ) { mesg += "(security is ON)"; } else { mesg += "(security is OFF)"; } logger.debug(mesg); } catch(Exception e) { logger.error(e.getMessage(), e); boss.setFailure(); } setHandshakeCompleted(); } } /** * Set status return value to false. */ public synchronized void setFailure() { success = false; } /** * Set status return value to success. */ public synchronized boolean getSuccess() { return success; } /** * Main method. Used for unit testing. */ public static void main(String[] args) { String certnick = "JSSCATestCert"; String testCipher = "1"; String testhost = "localhost"; int testport = 29755; int socketCntr = 1; String certDbPath = null; String passwdFile = null; String uploadFile = "foo.in"; String usage = "\nUSAGE:\n" + "java org.mozilla.jss.tests.JSS_FileUploadClient" + " [# sockets] [JSS cipher integer]\n[certdb path]" + " [password file] [upload test file] " + " [server host] [server port]"; try { if (args.length <= 0 || args[0].toLowerCase().equals("-h")) { System.out.println(usage); System.exit(1); } else { socketCntr = Integer.parseInt(args[0]); System.out.println("Socket Counter = " + socketCntr); } testCipher = args[1]; System.out.println("Test Cipher = " + testCipher); if ( args.length >= 3 ) { certDbPath = args[2]; passwdFile = args[3]; } if ( args.length >= 5 ) { uploadFile = args[4]; testhost = args[5]; testport = Integer.parseInt(args[6]); } } catch (Exception e) { } System.out.println("Client connecting to server ..."); for ( int j=0; j jssSupportedCiphers = new Vector<>(); private static SSLServerSocket serverSock = null; private static SSLSocket sock = null; private String fServerCertNick = null; private String fServerHost = "localhost"; private String fPasswordFile = "passwords"; private String fCertDbPath = "."; private boolean TestInetAddress = false; private boolean success = true; public static int port = 29755; public static String usage = "\nUSAGE:\njava "+ "JSS_FileUploadServer "+ "[certdb path] [password file]"+ "\n[server_host_name] " + "[cert nickname]" + "[testInetAddress: true|false]"; public static void main(String[] args) throws Exception { try { (new JSS_FileUploadServer()).doIt(args); } catch (Exception e) { System.out.println("Exception caught: " + e.getMessage()); System.exit(1); } System.exit(0); } public void doIt(String[] args) throws Exception { if ( args.length < 1 || args[0].toLowerCase().indexOf("-h") != -1) { System.out.println(usage); System.exit(1); } int socketCntr = 0; try { if (args[0].length() > 0 && !args[0].equals(".")) fCertDbPath = args[0]; if (args[1].length() > 0 && !args[1].equals("passwords")) fPasswordFile = args[1]; if (args[2].length() > 0 && !args[2].equals("localhost")) fServerHost = args[2]; if (args[3].length() > 0) fServerCertNick = args[3]; } catch (Exception e) {} CryptoManager cm = CryptoManager.getInstance(); CryptoToken tok = cm.getInternalKeyStorageToken(); PasswordCallback cb = new FilePasswordCallback(fPasswordFile); tok.login(cb); if (args[4].equalsIgnoreCase("true") == true) { TestInetAddress = true; } // We have to configure the server session ID cache before // creating any server sockets. SSLServerSocket.configServerSessionIDCache(10, 100, 100, null); //Disable SSL2 SSLSocket.enableSSL2Default(false); //Note we will use the NSS default enabled ciphers suites // open the server socket and bind to the port logger.debug("Server about .... to create socket"); if (TestInetAddress) { logger.debug("the HostName " + fServerHost + " the Inet Address " + InetAddress.getByName(fServerHost)); serverSock = new SSLServerSocket(port, 5, InetAddress.getByName(fServerHost), null , true); } else { logger.debug("Inet set to Null"); serverSock = new SSLServerSocket(port, 5, null , null , true); } logger.debug("Server created socket"); //serverSock.setSoTimeout(120 * 1000); serverSock.requireClientAuth(SSLSocket.SSL_REQUIRE_NO_ERROR); serverSock.setServerCertNickname(fServerCertNick); logger.debug("Server specified cert by nickname"); System.out.println("Server ready to accept connections"); while ( true ) { // accept the connection sock = (SSLSocket) serverSock.accept(); //sock.setKeepAlive(true); sock.addHandshakeCompletedListener( new HandshakeListener("server", this)); socketCntr++; readWriteThread rwThread = new readWriteThread(sock, socketCntr); rwThread.start(); } } /** * ReadWrite thread class that takes a * SSLSocket as input and sleeps * for 2 sec between sending some test * data and receiving. */ private class readWriteThread extends Thread { private SSLSocket socket = null; private int socketCntr = 0; public readWriteThread(SSLSocket sock, int cntr) { this.socket = sock; this.socketCntr = cntr; } @Override public void run() { try { String socketData = null; char[] cbuf = null; int readLength = 0; String readString = null; InputStream is = socket.getInputStream(); BufferedReader in = new BufferedReader( new InputStreamReader(is)); long timeInMs = new Date().getTime(); while ((readString = in.readLine()) != null) { long now = new Date().getTime(); System.out.print("Read " + readString.getBytes().length + "bytes in " + (now-timeInMs) + "\n"); timeInMs = now; } } catch (Exception e) { System.out.println("Exception caught in readWriteThread.run()\n"); e.printStackTrace(); System.exit(1); } } } public static class HandshakeListener implements SSLHandshakeCompletedListener { private String who; private JSS_FileUploadServer boss; public HandshakeListener(String who, JSS_FileUploadServer boss) { this.who = who; this.boss = boss; } @Override public void handshakeCompleted(SSLHandshakeCompletedEvent event) { try { String mesg = who + " got a completed handshake "; SSLSecurityStatus status = event.getStatus(); if( status.isSecurityOn() ) { mesg += "(security is ON)"; } else { mesg += "(security is OFF)"; } logger.debug(mesg); } catch(Exception e) { logger.error(e.getMessage(), e); boss.setFailure(); } } } public synchronized void setFailure() { success = false; } public synchronized boolean getSuccess() { return success; } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/JSS_SelfServClient.java000077500000000000000000001106131412550063600254620ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Iterator; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.crypto.X509Certificate; import org.mozilla.jss.ssl.SSLHandshakeCompletedEvent; import org.mozilla.jss.ssl.SSLHandshakeCompletedListener; import org.mozilla.jss.ssl.SSLSecurityStatus; import org.mozilla.jss.ssl.SSLSocket; import org.mozilla.jss.util.IncorrectPasswordException; import org.mozilla.jss.util.PasswordCallback; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /************** * Note on how to use JSS_SelfServServer and JSS_SelfServerClient * * For debugging purposes you should modify Constant.java debug_level to 4. * * First create db's and certificates * java -cp jss.jar org.mozilla.jss.tests.SetupDBs . ./passwords * java -cp jss.jar org.mozilla.jss.tests.GenerateTestCert . /passwords * localhost SHA-256/RSA CA_RSA Client_RSA Server_RSA * * Start the server: * * java -cp ./jss.jar org.mozilla.jss.tests.JSS_SelfServServer . passwords * localhost false 2921 verboseoff * * Start the client with 4 threads using ciphersuite 0x33. * Look at the file Constant.java for the ciphersuites values. * * java -cp jss.jar org.mozilla.jss.tests.JSS_SelfServClient 2 0x33 * . localhost 2921 verboseoff JSS Client_RSA * * If you envoke the client with a ciphersuite value -1 * then all current JSS ciphersuites will be tested fox X number of * threads, and once all ciphersuites have been tested the client * will closed all client SSLSockets and then tell the server to * shutdown. This case is for the nightly automated tests. * * java -cp jss.jar org.mozilla.jss.tests.JSS_SelfServClient 4 -1 * . passwords localhost 2921 verboseoff JSS */ interface ConstantsBase { // Test all implemented ciphersuites public static final int TEST_CIPHERS = -1; } public class JSS_SelfServClient implements ConstantsBase, Constants { public static Logger logger = LoggerFactory.getLogger(JSS_SelfServClient.class); private String clientCertNick = "default"; private String serverHost = "localhost"; private String ciphersuiteTested = null; private boolean TestCertCallBack = false; private boolean success = true; private int fCipher = TEST_CIPHERS; private int aWorkingCipher = 0; private boolean bTestCiphers = true; private String CipherName = null; private int port = 29754; private String EOF = "test"; private boolean handshakeCompleted = false; private boolean bVerbose = false; private boolean bFipsMode = false; /* ciphersuites to test */ private ArrayList ciphersToTest = new ArrayList<>(); private CryptoManager cm = null; private CryptoToken tok = null; private PasswordCallback cb = null; private String fPasswordFile = "passwords"; private String fCertDbPath = "."; private ArrayList sockList = new ArrayList<>(); /* h_ciphers is for ciphersuite that were able to successfully * connect to the server */ private ArrayList h_ciphers = new ArrayList<>(); /* f_ciphers is for ciphersuite that failed to connect to the server */ private ArrayList f_ciphers = new ArrayList<>(); private int sockID = 0; /* JSS only needs to be initailized for one instance */ private static boolean bJSS = false; private ThreadGroup socketThreads = new ThreadGroup("SSLSockets"); public void setTestCiphers(boolean t) { bTestCiphers = t; } public boolean getTestCiphers() { return bTestCiphers; } /** * Default Constructor. */ public JSS_SelfServClient() { if (logger.isDebugEnabled()) { bVerbose = true; } /* *if (bVerbose) { * for (int i = 0; i < jssCipherSuites.length; i++) { * System.out.println(jssCipherSuites[i].name + " " + * Integer.toHexString(jssCipherSuites[i].value) ); * } *} */ } public void setVerbose(boolean v) { bVerbose = v; } /** * returns true if JSS is sync with NSS ciphersuites. */ public boolean testJSSCiphersMatchNSS() { initJSS(); boolean cipherSuites = true; int ciphers[] = org.mozilla.jss.ssl.SSLSocket.getImplementedCipherSuites(); for (int i = 0; i < ciphers.length; i++) { //if we do not find the ciphersuite than the JSS // table is out of date. if (Constants.cipher.cipherToString(ciphers[i]) == null) { cipherSuites = false; System.out.println("JSS does not support ciphersuite: " + Integer.toHexString(ciphers[i])); } } if (!cipherSuites) { System.out.println("ERROR: NSS has implemented " + "ciphersuites that JSS does not support!\n"); System.out.println("see http://mxr.mozilla.org/nss/" + "source/lib/ssl/sslproto.h"); System.out.println("Update org/mozilla/jss/ssl/" + "SSLSocket.java"); System.out.println("Update org/mozilla/jss/tests/" + "Constants.java"); System.out.println("NSS implemented ciphersuites " + "missing from JSS"); } return cipherSuites; } public void configureDefaultSSLOptions() { initJSS(); try { //Disable SSL2 SSLSocket.enableSSL2Default(false); //if in FIPS mode disable SSL3 if (bFipsMode) SSLSocket.enableSSL3Default(false); } catch (SocketException ex) { ex.printStackTrace(); System.exit(1); } } public void configureCipherSuites(String server) { int ciphers[] = org.mozilla.jss.ssl.SSLSocket.getImplementedCipherSuites(); boolean testCipher; for (int i = 0; i < ciphers.length; ++i) { String ciphersuite = Constants.cipher.cipherToString(ciphers[i]); testCipher = true; if (bVerbose) { System.out.print(ciphersuite); } // This class uses the TLS versions that NSS enables by default. // Until NSS enables TLS 1.2 by default, don't test the cipher // suites that only work in TLS 1.2. if ((ciphersuite.indexOf("_SHA256") != -1) || (ciphersuite.indexOf("_SHA384") != -1) ) { if (bVerbose) System.out.print(" -"); testCipher = false; } if (server.equalsIgnoreCase("JSS")) { //For JSS SSLServer don't test if ((ciphersuite.indexOf("_DHE_") != -1) || (ciphersuite.indexOf("SSL2") != -1) || //Need to figure out why _ECDH_RSA don't work ( (ciphersuite.indexOf("RSA") != -1) && (ciphersuite.indexOf("_ECDH_") != -1)) ) { if (bVerbose) System.out.print(" -"); testCipher = false; } } if (server.equalsIgnoreCase("JSSE")) { //For JSSE SSLServers don't test if ((ciphersuite.indexOf("SSL2_") != -1) || (ciphersuite.indexOf("_ECDHE_") != -1) || (ciphersuite.indexOf("_ECDH_") != -1) || (ciphersuite.indexOf("_CAMELLIA_") != -1) || (ciphersuite.indexOf("_SEED_") != -1) || (ciphersuite.indexOf("_DHE_DSS_") != -1) || (ciphersuite.indexOf("_EXPORT1024_") != -1) || (ciphersuite.indexOf("_RSA_FIPS_") != -1) || (ciphersuite.indexOf("EXPORT_WITH_RC2") != -1) || (ciphersuite.indexOf("_ECDSA_") != -1) || (ciphersuite.indexOf("_256_") != -1) ) { if (bVerbose) System.out.print(" -"); testCipher = false; } } if (server.equalsIgnoreCase("Mozilla-JSS")) { //For JSSE Mozilla-JSS SSLServers don't test if ((ciphersuite.indexOf("SSL2_") != -1) || (ciphersuite.indexOf("_ECDHE_") != -1) || (ciphersuite.indexOf("_ECDH_") != -1) || (ciphersuite.indexOf("_CAMELLIA_") != -1) || (ciphersuite.indexOf("_SEED_") != -1) || (ciphersuite.indexOf("_DHE_DSS_") != -1)|| (ciphersuite.indexOf("_EXPORT1024_") != -1) || (ciphersuite.indexOf("_RSA_FIPS_") != -1) || (ciphersuite.indexOf("EXPORT_WITH_RC2") != -1) || (ciphersuite.indexOf("_ECDSA_") != -1) || (ciphersuite.indexOf( "SSL3_DHE_RSA_WITH_3DES_EDE_CBC_SHA") != -1) || (ciphersuite.indexOf( "SSL3_RSA_WITH_3DES_EDE_CBC_SHA") != -1) || (ciphersuite.indexOf( "SSL3_DHE_RSA_WITH_DES_CBC_SHA") != -1)|| (ciphersuite.indexOf( "SSL3_RSA_WITH_DES_CBC_SHA") != -1) || (ciphersuite.indexOf( "SSL3_RSA_EXPORT_WITH_RC4_40_MD5") != -1) || (ciphersuite.indexOf("_256_") != -1) ) { if (bVerbose) System.out.print(" -"); testCipher = false; } } if (testCipher) { if (bFipsMode) { try { if (SSLSocket.isFipsCipherSuite(ciphers[i])) { ciphersToTest.add(ciphers[i]); if (bVerbose) System.out.print(" - FIPS Testing"); } else if (bVerbose) System.out.print(" -"); } catch (SocketException ex) { ex.printStackTrace(); } } else { ciphersToTest.add(ciphers[i]); if (bVerbose) System.out.print(" - Testing"); } } } if (bVerbose) System.out.print("\n"); if(bVerbose) System.out.println("\nTesting " + ciphersToTest.size() + " ciphersuites."); } /** *For every enabled ciphersuite created numOfThreads connections. */ public void testCiphersuites(int numOfThreads) { Iterator iter = ciphersToTest.iterator(); setTestCiphers(true); while (iter.hasNext()) { setCipher(iter.next().intValue()); try { createSSLConnections(numOfThreads); } catch (Exception ex) { ex.printStackTrace(); System.exit(1); } } } /** * Initialize the desired ciphersuite to be set * on the socket. * @param aCipher */ public void setCipher(int aCipher) { initJSS(); int ciphers[] = org.mozilla.jss.ssl.SSLSocket.getImplementedCipherSuites(); ciphersuiteTested = Constants.cipher.cipherToString(aCipher); if (bVerbose || !bTestCiphers) { System.out.println("Testing " + Integer.toHexString(aCipher) + " " + ciphersuiteTested); } if (ciphersuiteTested != null) { fCipher = aCipher; } else { System.out.print("ciphersuite not supported"); System.exit(1); } try { if (cm.FIPSEnabled() && !SSLSocket.isFipsCipherSuite(aCipher)) { System.out.println("You are trying to test a non FIPS " + "ciphersuite when FIPS is enabled!"); System.exit(1); } } catch (SocketException ex) { ex.printStackTrace(); } //Disable all Ciphers we only want the one cipher //to be turned on for (int i = 0; i < ciphers.length; i++) { try { if (SSLSocket.getCipherPreferenceDefault(ciphers[i])) { // System.out.println("Implemented Cipher Suite: " + // Integer.toHexString(ciphers[i]) + " is ON"); SSLSocket.setCipherPreferenceDefault(ciphers[i], false); } } catch (SocketException ex) { ex.printStackTrace(); } } //note all ciphers are disabled but the ciphersuite to be tested //will only be enabled in the method createSSLSocket } /** * Initialize the hostname to run the server * @param aHostName */ public void setHostName(String aHostName) { serverHost = aHostName; } /** * Initialize the port to run the server * @param aPort */ public void setPort(int aPort) { port = aPort; } /** * Initialize the passwords file name * @param aPasswordFile */ public void setPasswordFile(String aPasswordFile) { fPasswordFile = aPasswordFile; } /** * Initialize the cert db path name * @param aCertDbPath */ public void setCertDbPath(String aCertDbPath) { fCertDbPath = aCertDbPath; } /** * Enable/disable Test Cert Callback. * @param aTestCertCallback */ public void setTestCertCallback(boolean aTestCertCallback) { TestCertCallBack = aTestCertCallback; } /** * Set client certificate * @param aClientCertNick Certificate Nick Name */ public void setClientCertNick(String aClientCertNick) { clientCertNick = aClientCertNick; X509Certificate certs[]; try { certs = cm.findCertsByNickname(clientCertNick); if (certs.length == 0) { System.out.println("unable to find cert nickname: " + clientCertNick); System.exit(1); } } catch (TokenException ex) { ex.printStackTrace(); System.exit(1); } } /** * Return true if handshake is completed * else return false; * @return handshake status */ public boolean isHandshakeCompleted() { return this.handshakeCompleted; } /** * Set handshakeCompleted flag to indicate * that the socket handshake is coplete. */ public void setHandshakeCompleted() { this.handshakeCompleted = true; } /** * Clear handshakeCompleted flag to indicate * that the system is now ready for another * socket connection. */ public void clearHandshakeCompleted() { this.handshakeCompleted = false; } /** * returns the total number SSLSockets created. */ public int getSockTotal() { return sockID; } /** * ReadWrite thread class that takes a * SSLSocket as input and sleeps * for 1 sec between sending some test * data and receiving. */ private class readWriteThread extends Thread { private SSLSocket clientSock = null; private String socketID = null; private String ciphersuite; public readWriteThread(ThreadGroup tgOb, String tName, String cs, SSLSocket sock) { super(tgOb, tName); if (bVerbose) { System.out.println("New thread: " + this); } ciphersuite = cs; clientSock = sock; socketID = tName; } @Override public void run() { try { String outputLine = null; String inputLine = null; InputStream is = clientSock.getInputStream(); OutputStream os = clientSock.getOutputStream(); BufferedReader bir = new BufferedReader( new InputStreamReader(is)); PrintWriter out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(os))); while (true) { outputLine = ciphersuite + ":" + socketID + "\n"; if (bVerbose) { System.out.println("Sending: " + outputLine); } out.print(outputLine); out.flush(); inputLine = bir.readLine(); if (bVerbose) { System.out.println("Received: " + inputLine + " on Client-" + socketID); } Thread.sleep(50); } } catch (InterruptedException e) { e.printStackTrace(); } catch (java.net.SocketTimeoutException e) { e.printStackTrace(); } catch (IOException e) { if ((e.getMessage().equalsIgnoreCase( "SocketException cannot read on socket")) || (e.getMessage().equalsIgnoreCase( "Socket has been closed, and cannot be reused.")) ) { //System.out.println("SSLSocket " // + socketID + " has been closed."); } else e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } } private void initJSS() { if (bJSS) { return; /* JSS already initialized */ } try { cm = CryptoManager.getInstance(); if (cm.FIPSEnabled()) { System.out.println("The database is in FIPSMODE"); bFipsMode = true; } tok = cm.getInternalKeyStorageToken(); cb = new FilePasswordCallback(fPasswordFile); tok.login(cb); bJSS = true; } catch (NotInitializedException ex) { ex.printStackTrace(); System.exit(1); } catch (IOException ex) { ex.printStackTrace(); System.exit(1); } catch (TokenException ex) { ex.printStackTrace(); System.exit(1); } catch (IncorrectPasswordException ex) { ex.printStackTrace(); System.exit(1); } } public boolean isServerAlive() { boolean isServerAlive = false; try { SSLSocket s = null; if (bVerbose) System.out.println("Confirming Server is alive "); //TLS_RSA_WITH_AES_128_CBC_SHA works in FIPS and Non FIPS mode. //and with JSS and JSSE SSL servers. setCipher(SSLSocket.TLS_RSA_WITH_AES_128_CBC_SHA); System.out.println("Testing Connection:" + serverHost + ":" + port); for (int i = 0; i < 20; i++) { s = createSSLSocket(); if (s != null) break; Thread.sleep(1000); } if (s != null) { s.close(); isServerAlive = true; } } catch (InterruptedException ex) { ex.printStackTrace(); System.exit(1); } catch (IOException ex) { ex.printStackTrace(); System.exit(1); } return isServerAlive; } /** * sendServerShutdownMsg */ public void sendServerShutdownMsg() { try { SSLSocket s = null; if (bVerbose) System.out.println("Sending shutdown message " + "to server."); if (aWorkingCipher == 0) { System.out.println("no ciphersuite was able to connect to " + "the server!"); System.exit(1); } setCipher(aWorkingCipher); s = createSSLSocket(); if (s == null) throw new IOException("Unable to connect to server"); OutputStream os = s.getOutputStream(); PrintWriter out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(os))); out.println("shutdown"); out.flush(); out.close(); s.close(); } catch (IOException ex) { ex.printStackTrace(); System.exit(1); } } /** * closes the SSLSocket */ public void closeAllSockets() { try { SSLSocket s; long start = System.currentTimeMillis(); Iterator sIter = sockList.iterator(); while (sIter.hasNext()) { s = sIter.next(); s.close(); } System.out.println("Waiting till all threads are dead"); int i = 0; while (socketThreads.activeCount() > 0) { Thread.sleep(10); System.out.println("ActiveCount" + socketThreads.activeCount()); //This loop should always exit but it has the potential //to hang the QA tests so... if (i == 100) { // 100 x 10 System.out.println("It is taking too long for the " + "threads to die. Exiting the program"); System.out.println("Time taken: " + (System.currentTimeMillis() - start) + " Milliseconds"); /* while all the threads have not completed cleanup. */ /* the functional test of each configured cihpersuite */ /* successfully established a connection. */ /* Let remaining threads die when this application */ /* ends execution */ return; } i++; } System.out.println("All threads are dead. Time taken: " + (System.currentTimeMillis() - start) + " Milliseconds."); } catch (IOException ex) { ex.printStackTrace(); System.exit(1); } catch (InterruptedException ex) { ex.printStackTrace(); System.exit(1); } } /** * returns a connected SSLSocket or null if unable to connect. */ private SSLSocket createSSLSocket() { SSLSocket sock = null; try { // connect to the server if ( bVerbose ) System.out.println("client about to connect..."); String hostAddr = InetAddress.getByName(serverHost).getHostAddress(); if ( bVerbose ) System.out.println("the host " + serverHost + " and the address " + hostAddr); if (TestCertCallBack) { if ( bVerbose ) System.out.println("calling approvalCallBack"); sock = new SSLSocket(InetAddress.getByName(hostAddr), port, null, 0, new TestCertificateApprovalCallback(), null); } else { if ( bVerbose ) System.out.println("NOT calling approvalCallBack"); sock = new SSLSocket(InetAddress.getByName(hostAddr), port); } if (clientCertNick.equalsIgnoreCase("default")) { sock.setClientCertNickname("Client_RSA"); sock.setClientCertNickname("Client_ECDSA"); sock.setClientCertNickname("Client_DSS"); } else { sock.setClientCertNickname(clientCertNick); if ( bVerbose ) { System.out.println("Client specified cert by nickname"); } } //Ensure the ciphersuite is disable, then enabled only it. if (sock.getCipherPreference(fCipher)) { System.out.println("Ciphersuite should have been disabled?"); System.exit(1); } else { sock.setCipherPreference(fCipher, true); } sock.addHandshakeCompletedListener( new HandshakeListener("client",this)); sock.forceHandshake(); sock.setSoTimeout(10*1000); sockList.add(sock); sockID++; aWorkingCipher = fCipher; if ( bVerbose ) { System.out.println("client connected"); } } catch (SocketException ex) { if (bTestCiphers) { sock = null; } else { ex.printStackTrace(); System.exit(1); } } catch (UnknownHostException ex) { ex.printStackTrace(); System.exit(1); } catch (IOException ex) { ex.printStackTrace(); System.exit(1); } return sock; } public void outputCipherResults() { String banner = new String ("\n-------------------------------------------------------\n"); System.out.println(banner); System.out.println("JSS has " + org.mozilla.jss.ssl.SSLSocket.getImplementedCipherSuites().length + " ciphersuites and " + ciphersToTest.size() + " were configured and tested."); if (ciphersToTest.size() == h_ciphers.size()) { System.out.println("All " + ciphersToTest.size() + " configured ciphersuites tested Successfully!\n"); } if (!h_ciphers.isEmpty()) { if (!f_ciphers.isEmpty()) { System.out.println(banner); System.out.println(h_ciphers.size() + " ciphersuites successfully connected to the "+ "server\n"); } Iterator iter = h_ciphers.iterator(); while (iter.hasNext()) { System.out.println(iter.next()); } } if (bFipsMode) { System.out.println("Note: ciphersuites that have the prefix " + "\"SSL\" or \"SSL3\" were used in TLS mode."); } if (ciphersToTest.size() != (h_ciphers.size() + f_ciphers.size())) { System.out.println("ERROR: did not test all expected ciphersuites"); } if (!f_ciphers.isEmpty()) { System.out.println(banner); System.out.println(f_ciphers.size() + " ciphersuites that did not connect to the "+ "server\n\n"); Iterator iter = f_ciphers.iterator(); while (iter.hasNext()) { System.out.println(iter.next()); } System.out.println("we should have no failed ciphersuites!"); System.exit(1); } System.out.println(banner); } /** * Initialize given number of SSLSocket client connection to the * SSLServer using the set parameters. Each Connection will have * a separate thread performing I/O to the Server. */ public void createSSLConnections(int numToCreate) throws Exception { SSLSocket sock = null; initJSS(); for (int i = 1; i <= numToCreate; i++) { sock = createSSLSocket(); if (sock != null) { String threadName = new String(sockID + "-" + i); readWriteThread rwThread = new readWriteThread(socketThreads, threadName, ciphersuiteTested, sock); rwThread.start(); if (i == 1) { h_ciphers.add(ciphersuiteTested); } } else { /* ciphersuite failed */ if (bTestCiphers) { f_ciphers.add(ciphersuiteTested); } break; } } if ( bVerbose ) { System.out.println("Active thread count: " + socketThreads.activeCount()); System.out.println("Total threads created: " + getSockTotal()); } } /** * SSL Handshake Listener implementation. */ public class HandshakeListener implements SSLHandshakeCompletedListener { private String who; private JSS_SelfServClient boss; public HandshakeListener(String who, JSS_SelfServClient boss) { this.who = who; this.boss = boss; } @Override public void handshakeCompleted(SSLHandshakeCompletedEvent event) { try { String mesg = who + " got a completed handshake "; SSLSecurityStatus status = event.getStatus(); if( status.isSecurityOn() ) { mesg += "(security is ON)"; } else { mesg += "(security is OFF)"; } if ( bVerbose ) { System.out.println(mesg); } } catch(Exception e) { e.printStackTrace(); System.exit(1); } setHandshakeCompleted(); } } /** * Set status return value to false. */ public synchronized void setFailure() { success = false; } /** * Set status return value to success. */ public synchronized boolean getSuccess() { return success; } /** * Main method. Used for unit testing. */ public static void main(String[] args) { String certnick = "default"; int testCipher = TEST_CIPHERS; String testhost = "localhost"; int testport = 29754; int numOfThreads = 10; String certDbPath = null; String passwdFile = null; boolean bVerbose = false; String server = "JSS"; try { Thread.sleep(3*1000); } catch (InterruptedException ex) { ex.printStackTrace(); } String usage = "\nUSAGE:\n" + "java org.mozilla.jss.tests.JSS_SelfServClient" + " [# sockets] [JSS cipher hex code \"0xC013\" value or -1] " + "\n\nOptional:\n" + "[certdb path] [password file] [server host] [server port]" + "[verbose] [server = JSS or JSSE] [ClientCert]"; try { if (args.length <= 0 || args[0].toLowerCase().equals("-h")) { System.out.println(usage); System.exit(1); } else { numOfThreads = Integer.parseInt(args[0]); System.out.println("Number of Threads to create: " + numOfThreads); } if (args.length >= 2) { if (args[1].startsWith("0x") || args[1].startsWith("0X")) { testCipher = Integer.decode(args[1]).intValue(); } else { testCipher = Integer.parseInt(args[1]); } } if (args.length >= 3) { certDbPath = args[2]; } if (args.length >= 4) { passwdFile = args[3]; } if (args.length >= 5) { testhost = args[4]; } if (args.length >= 6) { testport = Integer.parseInt(args[5]); } if ((args.length >= 7) && args[6].equalsIgnoreCase("verbose") == true) { System.out.println("verbose mode enabled."); bVerbose = true; } if (args.length >= 8) { server = args[7].toUpperCase(); } if (args.length >=9) { certnick = args[8]; System.out.println("certnickname: " + certnick); } } catch (Exception e) { System.out.println("Unknown exception : " + e.getMessage()); System.exit(1); } System.out.println("Client connecting to server: " + testhost + ":" + testport); JSS_SelfServClient jssTest = new JSS_SelfServClient(); try { if ( !testhost.equals("localhost") ) jssTest.setHostName(testhost); if ( testport != 29754 ) jssTest.setPort(testport); jssTest.setPasswordFile(passwdFile); jssTest.setCertDbPath(certDbPath); jssTest.setVerbose(bVerbose); jssTest.initJSS(); if (!jssTest.testJSSCiphersMatchNSS()) { System.out.println("JSS needs to update the ciphersuites!"); System.exit(1); } jssTest.setTestCertCallback(true); jssTest.configureDefaultSSLOptions(); if ( certDbPath != null ) jssTest.setCertDbPath(certDbPath); if ( passwdFile != null ) jssTest.setPasswordFile(passwdFile); if (!jssTest.isServerAlive()) { System.out.println("Server " + testhost + ":" + testport + " is not Alive.\nIf this test was ran by " + "all.pl look at the server invocation for failures " + "and check network issues."); System.exit(1); } if (testCipher != TEST_CIPHERS) { jssTest.setClientCertNick(certnick); jssTest.setTestCiphers(false); jssTest.setCipher(testCipher); jssTest.createSSLConnections(numOfThreads); } else { jssTest.configureCipherSuites(server); jssTest.testCiphersuites(numOfThreads); } } catch (Exception ex) { System.out.println(ex.getMessage()); ex.printStackTrace(); System.exit(1); } if (jssTest.getSockTotal() == 0 ) { System.out.println("No SSLSockets created check your " + "configuration."); System.exit(1); } // choose how to exit the program System.out.println(jssTest.getSockTotal() + " SSLSockets created."); System.out.println("Each created SSLSocket is reading/writing to" + " the SSLServer."); if (jssTest.getTestCiphers()) { try { //Sleep for 30 seconds Thread.sleep(30*1000); } catch (InterruptedException ex) { ex.printStackTrace(); System.exit(1); } jssTest.closeAllSockets(); jssTest.sendServerShutdownMsg(); jssTest.outputCipherResults(); System.exit(0); } System.out.println("You can choose to exit the program enter:" + "\n\t\'A\' to abort with out closing the sockets." + "\n\t\'C\' to close all client sockets (server will not quit)" + "\n\tor any other letter to close all sockets and tell the" + "server to quit."); try { BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in)); String p = stdin.readLine(); if (p.equalsIgnoreCase("a")) { System.out.println("Aborting with out closing SSLSockets."); } else { jssTest.closeAllSockets(); if (!p.equalsIgnoreCase("c")) { //shutdown the server jssTest.sendServerShutdownMsg(); } } } catch (IOException ex) { ex.printStackTrace(); System.exit(1); } System.exit(0); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/JSS_SelfServServer.java000077500000000000000000000343531412550063600255200ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetAddress; import java.net.SocketTimeoutException; import java.util.Vector; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.ssl.SSLHandshakeCompletedEvent; import org.mozilla.jss.ssl.SSLHandshakeCompletedListener; import org.mozilla.jss.ssl.SSLSecurityStatus; import org.mozilla.jss.ssl.SSLServerSocket; import org.mozilla.jss.ssl.SSLSocket; import org.mozilla.jss.util.PasswordCallback; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /************** * Note on how to use JSS_SelfServServer and JSS_SelfServerClient * * For debugging purposes you should modify Constant.java debug_level to 4. * * First create db's and certificates * java -cp jss.jar org.mozilla.jss.tests.SetupDBs . ./passwords * java -cp jss.jar org.mozilla.jss.tests.GenerateTestCert . /passwords * localhost SHA-256/RSA CA_RSA Client_RSA Server_RSA * * Start the server: * * java -cp ./jss.jar org.mozilla.jss.tests.JSS_SelfServServer . passwords localhost * false 2921 verboseoff * * Start the client with 4 threads using ciphersuite 0x33. * Look at the file Constant.java for the ciphersuites values. * * java -cp jss.jar org.mozilla.jss.tests.JSS_SelfServClient 2 0x33 * . localhost 2921 verboseoff JSS Client_RSA * * If you envoke the client with a ciphersuite value -1 * then all current JSS ciphersuites will be tested fox X number of * threads, and once all ciphersuites have been tested the client * will closed all client SSLSockets and then tell the server to * shutdown. This case is for the nightly automated tests. * * java -cp jss.jar org.mozilla.jss.tests.JSS_SelfServClient 4 -1 * . passwords localhost 2921 verboseoff JSS */ public class JSS_SelfServServer { public static Logger logger = LoggerFactory.getLogger(JSS_SelfServServer.class); private static Vector jssSupportedCiphers = new Vector<>(); private static SSLServerSocket serverSock = null; private static SSLSocket sock = null; public static void main(String[] args) throws Exception { try { (new JSS_SelfServServer()).doIt(args); } catch (Exception e) { System.out.println("JSS_SelfServServer exiting with Exception " + e.getMessage()); System.exit(1); } System.exit(0); } private String fServerCertNick = null; private String fServerHost = "localhost"; private String fPasswordFile = "passwords"; private String fCertDbPath = "."; private boolean TestInetAddress = false; private boolean success = true; private boolean bVerbose = false; public int port = 29754; public static String usage = "\nUSAGE:\njava JSS_SelfServServer"+ " [certdb path] [password file]\n"+ "[server_host_name] [testInetAddress: true|false]" + " "; public JSS_SelfServServer() { if (logger.isDebugEnabled()) { bVerbose = true; } } public void doIt(String[] args) throws Exception { if ( args.length < 5 || args[0].toLowerCase().equals("-h")) { System.out.println(usage); System.exit(1); } try { if (!args[0].equals(".")) fCertDbPath = args[0]; if (!args[1].equals("passwords")) fPasswordFile = args[1]; if (!args[2].equals("localhost")) fServerHost = args[2]; if (args[3].equalsIgnoreCase("true") == true) TestInetAddress = true; if (args.length >= 5) port = Integer.parseInt(args[4]); if (args.length >=6 && args[5].equalsIgnoreCase("verbose")) { bVerbose = true; } if (args.length >=7 && !args[6].equalsIgnoreCase("default")) { fServerCertNick = args[6]; } } catch (NumberFormatException e) { System.out.println("Error parsing command line " + e.getMessage()); System.out.println(usage); System.exit(1); } if (bVerbose) System.out.println("initializing JSS"); CryptoManager cm = CryptoManager.getInstance(); CryptoToken tok = cm.getInternalKeyStorageToken(); PasswordCallback cb = new FilePasswordCallback(fPasswordFile); tok.login(cb); // We have to configure the server session ID cache before // creating any server sockets. SSLServerSocket.configServerSessionIDCache(10, 100, 100, null); if (cm.FIPSEnabled()) { /* turn on only FIPS ciphersuites */ /* Disable SSL2 and SSL3 ciphers */ SSLSocket.enableSSL2Default(false); SSLSocket.enableSSL3Default(false); //Enable only FIPS ciphersuites. int ciphers[] = org.mozilla.jss.ssl.SSLSocket.getImplementedCipherSuites(); for (int i = 0; i < ciphers.length; ++i) { if (SSLSocket.isFipsCipherSuite(ciphers[i])) { /* enable the FIPS ciphersuite */ SSLSocket.setCipherPreferenceDefault(ciphers[i], true); } else if (SSLSocket.getCipherPreferenceDefault( ciphers[i])) { /* disable the non fips ciphersuite */ SSLSocket.setCipherPreferenceDefault(ciphers[i], false); } } } else { /* turn on all implemented ciphersuites the server certificate * will determine if the ciphersuites can be used. */ int ciphers[] = org.mozilla.jss.ssl.SSLSocket.getImplementedCipherSuites(); for (int i = 0; i < ciphers.length; ++i) { try { SSLSocket.setCipherPreferenceDefault(ciphers[i], true); if (bVerbose) { System.out.println(Constants.cipher.cipherToString( ciphers[i]) + " " + Integer.toHexString(ciphers[i])); } } catch (Exception ex) { ex.printStackTrace(); System.exit(1); } } //disable SSL2 ciphersuites SSLSocket.enableSSL2Default(false); } // open the server socket and bind to the port if (bVerbose) System.out.println("JSS_SelfServServ about .... to create socket"); if (TestInetAddress) { if (bVerbose) System.out.println("JSS_SelfServServ HostName " + fServerHost + " the Inet Address " + InetAddress.getByName(fServerHost)); serverSock = new SSLServerSocket(port, 5, InetAddress.getByName(fServerHost), null , true); } else { if (bVerbose) System.out.println("Inet set to Null"); serverSock = new SSLServerSocket(port, 5, null , null , true); } if (bVerbose) System.out.println("JSS_SelfServServ created socket"); serverSock.setSoTimeout(600*1000); // Set timeout for 10 minutes serverSock.requireClientAuth(SSLSocket.SSL_REQUIRE_NO_ERROR); serverSock.setServerCertNickname("Server_ECDSA"); serverSock.setServerCertNickname("Server_RSA"); serverSock.setServerCertNickname("Server_DSS"); if (bVerbose) System.out.println("JSS_SelfServServ specified cert by nickname"); System.out.println("JSS_SelfServServ " + fServerHost + " ready to accept connections on " + port); int socketCntr = 0; try { while ( true ) { // accept the connection sock = (SSLSocket) serverSock.accept(); sock.addHandshakeCompletedListener( new HandshakeListener("server", this)); socketCntr++; sock.setSoTimeout(300*1000); if (bVerbose) { System.out.println("Timeout value for SSL sockets: " + sock.getSoTimeout() + " milliseconds"); } readWriteThread rwThread = new readWriteThread(sock, socketCntr); rwThread.start(); } } catch (SocketTimeoutException ex) { if (socketCntr == 0) { System.out.println("JSS_SelfServServ No Client attempted to " + "connect! If " + "test ran from all.pl check the client execution " + "for errors."); } else { System.out.println("JSS_SelfServServ there has been " + socketCntr + " client " + " connections but the server Accept has timed out!"); } System.out.println("JSS_SelfServServ Timeout value: " + serverSock.getSoTimeout() + " milliseconds"); ex.printStackTrace(); System.out.println("JSS_SelfServServ exiting due to timeout."); System.exit(1); } catch (Exception ex) { System.out.println("JSS_SelfServServ Exception:"); ex.printStackTrace(); System.out.println("JSS_SelfServServ exiting."); System.exit(1); } } /** * ReadWrite thread class that takes a * SSLSocket as input and read then writes * back to client. */ private class readWriteThread extends Thread { private SSLSocket socket = null; private int socketCntr = 0; public readWriteThread(SSLSocket sock, int cntr) { this.socket = sock; this.socketCntr = cntr; } @Override public void run() { try { String inputLine = null; String outputLine = null; InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); BufferedReader bir = new BufferedReader( new InputStreamReader(is)); PrintWriter out = new PrintWriter(new BufferedWriter( new OutputStreamWriter(os))); while (true) { try { if ((inputLine = bir.readLine()) != null) { if (inputLine.equalsIgnoreCase("shutdown")) { if (bVerbose) { System.out.println("Client told " + " JSS_SelfServServer to Shutdown!"); } is.close(); os.close(); socket.close(); System.exit(0); } outputLine = "ServerSSLSocket- " + socketCntr; if (bVerbose) { System.out.println("ServerSSLSocket-" + socketCntr + ": Received " + inputLine); System.out.println("Sending" + outputLine); } out.println(outputLine); out.flush(); } else { /* if you read null then quit. otherwise you * will be in endless loop with the socket * stuck in CLOSED_WAIT. */ if (bVerbose) { System.out.println("ServerSSLSocket-" + socketCntr + " read null aborting connection."); } break; } } catch (SocketTimeoutException ste) { System.out.println("ServerSSLSocket-" + socketCntr + " timed out: " + ste.toString()); break; } catch (IOException ex) { break; } } /* close streams and close socket */ is.close(); os.close(); socket.close(); if (bVerbose) { System.out.println("ServerSSLSocket " + socketCntr + " has been Closed."); } } catch (IOException e) { e.printStackTrace(); } } } public static class HandshakeListener implements SSLHandshakeCompletedListener { private String who; private JSS_SelfServServer boss; public HandshakeListener(String who, JSS_SelfServServer boss) { this.who = who; this.boss = boss; } @Override public void handshakeCompleted(SSLHandshakeCompletedEvent event) { try { String mesg = who + " got a completed handshake "; SSLSecurityStatus status = event.getStatus(); if( status.isSecurityOn() ) { mesg += "(security is ON)"; } else { mesg += "(security is OFF)"; } logger.debug(mesg); } catch(Exception e) { logger.error(e.getMessage(), e); boss.setFailure(); } } } public synchronized void setFailure() { success = false; } public synchronized boolean getSuccess() { return success; } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/KeyFactoryTest.java000066400000000000000000000153031412550063600247700ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.Signature; import java.security.spec.DSAPrivateKeySpec; import java.security.spec.DSAPublicKeySpec; import java.security.spec.KeySpec; import java.security.spec.RSAPrivateCrtKeySpec; import java.security.spec.RSAPublicKeySpec; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.Policy; import org.mozilla.jss.util.PasswordCallback; import org.slf4j.Logger; import org.slf4j.LoggerFactory; abstract class TestValues { protected TestValues(String keyGenAlg, String sigAlg, Class privateKeySpecClass, Class publicKeySpecClass, String provider) { this.keyGenAlg = keyGenAlg; this.sigAlg = sigAlg; this.privateKeySpecClass = privateKeySpecClass; this.publicKeySpecClass = publicKeySpecClass; this.provider = provider; } public final String keyGenAlg; public final String sigAlg; public final Class privateKeySpecClass; public final Class publicKeySpecClass; public final String provider; } class RSATestValues extends TestValues { public RSATestValues() { super("RSA", "SHA512withRSA", RSAPrivateCrtKeySpec.class, RSAPublicKeySpec.class, "SunRsaSign"); } public RSATestValues(String provider) { super("RSA", "SHA512withRSA", RSAPrivateCrtKeySpec.class, RSAPublicKeySpec.class, provider); } } class DSATestValues extends TestValues { public DSATestValues() { super("DSA", "SHA512withDSA", DSAPrivateKeySpec.class, DSAPublicKeySpec.class, "SUN"); } public DSATestValues(String provider) { super("DSA", "SHA512withDSA", DSAPrivateKeySpec.class, DSAPublicKeySpec.class, provider); } } public class KeyFactoryTest { public static Logger logger = LoggerFactory.getLogger(KeyFactoryTest.class); public static void main(String argv[]) throws Throwable { if( argv.length < 2 ) { System.out.println( "Usage: java org.mozilla.jss.tests.KeyFactoryTest " + " "); System.exit(1); } CryptoToken tok = CryptoManager.getInstance().getInternalKeyStorageToken(); PasswordCallback cb = new FilePasswordCallback(argv[1]); tok.login(cb); /* This is just a huge amount of needless info for the tinderbox and nightly QA * Provider []provs = Security.getProviders(); * for( int i=0; i < provs.length; ++i) { * System.out.println("======"); * System.out.println(provs[i].getName()); * provs[i].list(System.out); * System.out.println("======"); * } */ (new KeyFactoryTest()).doTest(); } public void doTest() throws Throwable { RSATestValues rsa = new RSATestValues(); boolean exception = false; // Generate RSA private key from spec genPrivKeyFromSpec(rsa); // translate RSA key genPubKeyFromSpec(rsa); } void genPrivKeyFromSpec(TestValues vals) throws Throwable { // generate the key pair KeyPairGenerator kpg = KeyPairGenerator.getInstance(vals.keyGenAlg, vals.provider); if (vals.keyGenAlg.equalsIgnoreCase("RSA")) { kpg.initialize(Policy.RSA_MINIMUM_KEY_SIZE); } else if (vals.keyGenAlg.equalsIgnoreCase("DSA")) { kpg.initialize(Policy.DSA_MINIMUM_KEY_SIZE); } else { throw new IllegalArgumentException("Unknown algorithm type: " + vals.keyGenAlg); } KeyPair pair = kpg.generateKeyPair(); // get the private key spec KeyFactory sunFact = KeyFactory.getInstance(vals.keyGenAlg, vals.provider); KeySpec keySpec = sunFact.getKeySpec(pair.getPrivate(), vals.privateKeySpecClass); // import it into JSS KeyFactory jssFact = KeyFactory.getInstance(vals.keyGenAlg, "Mozilla-JSS"); PrivateKey jssPrivk = jssFact.generatePrivate(keySpec); signVerify(vals.sigAlg, jssPrivk, "Mozilla-JSS", pair.getPublic(), vals.provider); System.out.println("Successfully generated a " + vals.keyGenAlg + " private key from a " + vals.privateKeySpecClass.getName()); } public void signVerify(String sigAlg, PrivateKey privk, String signProv, PublicKey pubk, String verifyProv) throws Throwable { Signature signSig = Signature.getInstance(sigAlg, signProv); signSig.initSign(privk); String toBeSigned = "blah blah blah sign me"; signSig.update(toBeSigned.getBytes("UTF-8")); byte[] signature = signSig.sign(); Signature verSig = Signature.getInstance(sigAlg, verifyProv); verSig.initVerify(pubk); verSig.update(toBeSigned.getBytes("UTF-8")); if( ! verSig.verify(signature) ) { throw new Exception( "Private/public key mismatch: signing alg=" + sigAlg + ", signing provider=" + signProv + ", verifying provider = " + verifyProv); } } void genPubKeyFromSpec(TestValues vals) throws Throwable { // generate a key pair KeyPairGenerator kpg = KeyPairGenerator.getInstance(vals.keyGenAlg, vals.provider); if (vals.keyGenAlg.equalsIgnoreCase("RSA")) { kpg.initialize(Policy.RSA_MINIMUM_KEY_SIZE); } else if (vals.keyGenAlg.equalsIgnoreCase("DSA")) { kpg.initialize(Policy.DSA_MINIMUM_KEY_SIZE); } else { throw new IllegalArgumentException("Unknown algorithm type: " + vals.keyGenAlg); } KeyPair pair = kpg.generateKeyPair(); // get the public key spec KeyFactory sunFact = KeyFactory.getInstance(vals.keyGenAlg, vals.provider); KeySpec keySpec = sunFact.getKeySpec(pair.getPublic(), vals.publicKeySpecClass); // import it into JSS KeyFactory jssFact = KeyFactory.getInstance(vals.keyGenAlg, "Mozilla-JSS"); PublicKey jssPubk = jssFact.generatePublic(keySpec); signVerify(vals.sigAlg, pair.getPrivate(), vals.provider, jssPubk, "Mozilla-JSS"); System.out.println("Successfully generated a " + vals.keyGenAlg + " public key from a " + vals.publicKeySpecClass.getName()); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/KeyStoreTest.java000066400000000000000000000147651412550063600244700ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.security.Key; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.KeyStore; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.util.Enumeration; import javax.crypto.SecretKey; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.KeyGenAlgorithm; import org.mozilla.jss.crypto.KeyGenerator; import org.mozilla.jss.crypto.SecretKeyFacade; public class KeyStoreTest { public static void printUsage() { System.out.println("Usage: KeyStoreTest " + " [...]"); System.out.println("Operations:\n" + "getAliases\n" + "deleteEntry . . .\n" + "getCertByName . . .\n" + "getCertByDER \n" + "getKey \n" + "addKey \n" + "isTrustedCert \n"); } public static void main(String argv[]) throws Throwable { if( argv.length < 2 ) { printUsage(); System.exit(1); } String password_file = argv[1]; String op = argv[2]; int offset = 3; String[] args = new String[argv.length - offset]; for(int i = offset; i < argv.length; i++) { args[i - offset] = argv[i]; } CryptoManager cm = CryptoManager.getInstance(); // login to the token CryptoToken token = cm.getInternalKeyStorageToken(); //CryptoToken token = cm.getTokenByName("Builtin Object Token"); token.login(new FilePasswordCallback(password_file)); cm.setThreadToken(token); KeyStore ks = KeyStore.getInstance("PKCS11", "Mozilla-JSS"); ks.load(null, null); if( op.equalsIgnoreCase("getAliases") ) { dumpAliases(ks); } else if( op.equalsIgnoreCase("deleteEntry") ) { for(int j=0; j < args.length; ++j) { ks.deleteEntry(args[j]); } } else if( op.equalsIgnoreCase("getCertByName") ) { for(int j=0; j < args.length; ++j) { dumpCert(ks, args[j]); } } else if( op.equalsIgnoreCase("getCertByDER") ) { if( args.length < 1 ) { printUsage(); System.exit(1); } getCertByDER(ks, args[0]); } else if( op.equalsIgnoreCase("getKey") ) { if( args.length != 1 ) { printUsage(); System.exit(1); } getKey(ks, args[0]); } else if( op.equalsIgnoreCase("isTrustedCert") ) { if( args.length != 1 ) { printUsage(); System.exit(1); } isTrustedCert(ks, args[0]); } else if( op.equalsIgnoreCase("addKey") ) { if( args.length != 1 ) { printUsage(); System.exit(1); } addKey(ks, args[0]); } else { printUsage(); System.exit(1); } } public static void dumpCert(KeyStore ks, String alias) throws Throwable { Certificate cert = ks.getCertificate(alias); if( cert == null ) { System.out.println("Certificate with alias \"" + alias + "\" not found"); } else { System.out.println(cert.toString()); } } public static void dumpAliases(KeyStore ks) throws Throwable { Enumeration aliases = ks.aliases(); System.out.println("Aliases:"); while( aliases.hasMoreElements() ) { String alias = aliases.nextElement(); System.out.println( "\"" + alias + "\""); } System.out.println(); } public static void getCertByDER(KeyStore ks, String derCertFilename) throws Throwable { ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] buf = new byte[1024]; int numRead; try (FileInputStream fis = new FileInputStream(derCertFilename)) { while ((numRead = fis.read(buf)) != -1) { bos.write(buf, 0, numRead); } } ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); CertificateFactory fact = CertificateFactory.getInstance("X.509"); Certificate cert = fact.generateCertificate( bis ); String nick = ks.getCertificateAlias(cert); if( nick == null ) { System.out.println("No matching certificate was found."); } else { System.out.println("Found matching certificate \"" + nick + "\""); } } public static void getKey(KeyStore ks, String alias) throws Throwable { Key key = ks.getKey(alias, null); if( key == null ) { System.out.println("Could not find key for alias \"" + alias + "\""); System.exit(1); } else { String clazz = key.getClass().getName(); System.out.println("Found " + clazz + " for alias \"" + alias + "\""); } } public static void isTrustedCert(KeyStore ks, String alias) throws Throwable { if( ks.isCertificateEntry(alias) ) { System.out.println("\"" + alias + "\" is a trusted certificate" + " entry"); } else { System.out.println("\"" + alias + "\" is NOT a trusted certificate" + " entry"); } } public static void addKey(KeyStore ks, String alias) throws Throwable { KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "Mozilla-JSS"); kpg.initialize(1024); KeyPair pair = kpg.genKeyPair(); Certificate [] certs = new Certificate[1]; ks.setKeyEntry(alias, pair.getPrivate(), null, certs); CryptoManager cm = CryptoManager.getInstance(); CryptoToken tok = cm.getInternalKeyStorageToken(); KeyGenerator kg = tok.getKeyGenerator( KeyGenAlgorithm.DES3 ); SecretKey key = new SecretKeyFacade(kg.generate()); ks.setKeyEntry(alias+"sym", key, null, null); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/KeyWrapping.java000066400000000000000000000157501412550063600243160ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.security.KeyPair; import java.security.spec.MGF1ParameterSpec; import javax.crypto.spec.PSource; import javax.crypto.spec.OAEPParameterSpec; import org.mozilla.jss.crypto.*; import org.mozilla.jss.CryptoManager; /** * Keywrapping tests.. * */ public class KeyWrapping { public static void main(String args[]) throws Exception { CryptoManager cm = CryptoManager.getInstance(); CryptoToken token = cm.getInternalCryptoToken(); CryptoToken keyToken = cm.getInternalKeyStorageToken(); KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.AES); KeyGenerator keyKg = keyToken.getKeyGenerator(KeyGenAlgorithm.AES); kg.initialize(256); keyKg.initialize(256); SymmetricKey wrapped = kg.generate(); SymmetricKey wrapper = kg.generate(); SymmetricKey keyWrapper = keyKg.generate(); SymmetricKey keyWrapped = keyKg.clone(wrapped); // wrap a symmetric with a symmetric byte[] plaintextPre = new byte[] { (byte)0x73, (byte)0x24, (byte)0x51, (byte)0x48, (byte)0x32, (byte)0x87, (byte)0x23, (byte)0x33, (byte)0x65, (byte)0x5f, (byte)0x73, (byte)0x9e, (byte)0x8b, (byte)0xb6, (byte)0x69, (byte)0x90 }; byte[] plaintext = Cipher.pad(plaintextPre, EncryptionAlgorithm.AES_256_ECB.getBlockSize()); System.out.println("plaintext length is " + plaintext.length); Cipher encryptor = token.getCipherContext(EncryptionAlgorithm.AES_256_ECB); encryptor.initEncrypt(wrapped); byte[] ciphertext = encryptor.doFinal(plaintext); System.out.println("ciphertext length is " + ciphertext.length); KeyWrapper keyWrap = token.getKeyWrapper(KeyWrapAlgorithm.AES_ECB); keyWrap.initWrap(wrapper,null); byte[] wrappedKey = keyWrap.wrap(wrapped); keyWrap.initUnwrap(wrapper, null); SymmetricKey unwrapped = keyWrap.unwrapSymmetric(wrappedKey, SymmetricKey.AES, SymmetricKey.Usage.DECRYPT, 0); Cipher decryptor = token.getCipherContext(EncryptionAlgorithm.AES_256_ECB); decryptor.initDecrypt(unwrapped); byte[] recoveredPre = decryptor.doFinal(ciphertext); System.out.println("Decrypted "+ recoveredPre.length+ " bytes"); byte[] recovered = Cipher.unPad(recoveredPre, EncryptionAlgorithm.AES_256_ECB.getBlockSize()); System.out.println("plaintext:"); displayByteArray(plaintextPre); System.out.println("ciphertext:"); displayByteArray(ciphertext); System.out.println("recovered:"); displayByteArray(recovered); // wrap a private with a symmetric keyWrap = keyToken.getKeyWrapper(KeyWrapAlgorithm.AES_CBC_PAD); IVParameterSpec iv = new IVParameterSpec(recovered); keyWrap.initWrap(keyWrapper, iv); KeyPairGenerator kpg = keyToken.getKeyPairGenerator(KeyPairAlgorithm.RSA); kpg.initialize(Policy.RSA_MINIMUM_KEY_SIZE); kpg.temporaryPairs(true); KeyPair kp = kpg.genKeyPair(); java.security.PublicKey pub = kp.getPublic(); PrivateKey privk = (org.mozilla.jss.crypto.PrivateKey)kp.getPrivate(); wrappedKey = keyWrap.wrap(privk); System.out.println("Original key:"); displayByteArray(privk.getUniqueID()); privk = null; kp = null; keyWrap.initUnwrap(keyWrapper, iv); PrivateKey newPrivk = keyWrap.unwrapTemporaryPrivate(wrappedKey, PrivateKey.RSA, pub ); // wrap a private with a symmetric using AES_KEY_WRAP_PAD keyWrap = keyToken.getKeyWrapper(KeyWrapAlgorithm.AES_KEY_WRAP_PAD); // IVParameterSpec iv = new IVParameterSpec(recovered); keyWrap.initWrap(keyWrapper, null /*iv*/); KeyPairGenerator kpg2 = keyToken.getKeyPairGenerator(KeyPairAlgorithm.RSA); kpg2.initialize(Policy.RSA_MINIMUM_KEY_SIZE); kpg2.temporaryPairs(true); KeyPair kp2 = kpg2.genKeyPair(); java.security.PublicKey pub2 = kp2.getPublic(); PrivateKey privk2 = (org.mozilla.jss.crypto.PrivateKey)kp2.getPrivate(); wrappedKey = keyWrap.wrap(privk2); System.out.println("Original key:"); displayByteArray(privk2.getUniqueID()); privk2 = null; kp2 = null; //keyToken.getCryptoStore().deletePrivateKey(privk); keyWrap.initUnwrap(keyWrapper, null /*iv*/); PrivateKey newPrivk2 = keyWrap.unwrapTemporaryPrivate(wrappedKey, PrivateKey.RSA, pub ); System.out.println("New key:"); displayByteArray(newPrivk2.getUniqueID()); System.out.println("New key:"); displayByteArray(newPrivk2.getUniqueID()); // wrap a symmetric with a private keyWrap = keyToken.getKeyWrapper(KeyWrapAlgorithm.RSA); keyWrap.initWrap(pub,null); wrappedKey = keyWrap.wrap(keyWrapped); System.out.println("Wrapped key:"); displayByteArray(wrappedKey); keyWrap.initUnwrap(newPrivk, null); unwrapped = keyWrap.unwrapSymmetric(wrappedKey, SymmetricKey.AES, SymmetricKey.Usage.DECRYPT, 0); unwrapped = kg.clone(unwrapped); decryptor = token.getCipherContext(EncryptionAlgorithm.AES_256_ECB); decryptor.initDecrypt(unwrapped); recovered = decryptor.doFinal(ciphertext); System.out.println("Recovered again:"); displayByteArray(Cipher.unPad(recovered, EncryptionAlgorithm.AES_256_ECB.getBlockSize())); // try a RSA-OAEP operation keyWrap = keyToken.getKeyWrapper(KeyWrapAlgorithm.RSA_OAEP); OAEPParameterSpec config = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSource.PSpecified.DEFAULT); keyWrap.initWrap(pub, config); wrappedKey = keyWrap.wrap(keyWrapped); System.out.println("Wrapped key:"); displayByteArray(wrappedKey); keyWrap.initUnwrap(newPrivk, config); unwrapped = keyWrap.unwrapSymmetric(wrappedKey, SymmetricKey.AES, SymmetricKey.Usage.DECRYPT, 0); unwrapped = kg.clone(unwrapped); decryptor = token.getCipherContext(EncryptionAlgorithm.AES_256_ECB); decryptor.initDecrypt(unwrapped); recovered = decryptor.doFinal(ciphertext); System.out.println("Recovered again:"); displayByteArray(Cipher.unPad(recovered, EncryptionAlgorithm.AES_256_ECB.getBlockSize())); } public static void displayByteArray(byte[] ba) { System.out.print("[" + ba.length + " bytes] "); for(int i=0; i < ba.length; i++) { System.out.print( Integer.toHexString(ba[i]&0xff) + " " ); if( (i % 26) == 25 ) { System.out.println(""); } } System.out.println(""); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/ListCACerts.java000066400000000000000000000022051412550063600241650ustar00rootroot00000000000000package org.mozilla.jss.tests; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.crypto.*; public class ListCACerts { public static void main(String args[]) throws Exception { if (args.length > 2) { System.out.println( "Usage: java org.mozilla.jss.tests.ListCACerts [verbose]"); System.exit(1); } CryptoManager cm = CryptoManager.getInstance(); X509Certificate[] certs = cm.getCACerts(); System.out.println("Number of CA certs: " + certs.length); System.out.println("use option \"verbose\" if you want the CA " + "certs printed out"); if (args.length == 2 && args[1].equalsIgnoreCase("verbose")) { for (int i = 0; i < certs.length; i++) { System.out.println(certs[i].getSubjectDN().toString()); InternalCertificate ic = (InternalCertificate) certs[i]; System.out.println("SSL: " + ic.getSSLTrust() + ", Email: " + ic.getEmailTrust() + ", Object Signing: " + ic.getObjectSigningTrust()); } } } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/ListCerts.java000066400000000000000000000103711412550063600237640ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.io.ByteArrayInputStream; import java.security.cert.CertificateFactory; import java.util.Iterator; import java.util.Set; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.asn1.ASN1Util; import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; import org.mozilla.jss.asn1.OCTET_STRING; import org.mozilla.jss.asn1.SEQUENCE; import org.mozilla.jss.crypto.X509Certificate; import org.mozilla.jss.pkix.cert.Certificate; import org.mozilla.jss.pkix.cert.CertificateInfo; import org.mozilla.jss.pkix.cert.Extension; public class ListCerts { public static void main(String args[]) { try { if( args.length != 2 ) { System.out.println("Usage: ListCerts "); return; } String nickname = args[1]; CryptoManager cm = CryptoManager.getInstance(); X509Certificate[] certs = cm.findCertsByNickname(nickname); System.out.println(certs.length + " certs found with this nickname."); for(int i=0; i < certs.length; i++) { System.out.println("\nSubject: "+certs[i].getSubjectDN()); Certificate cert = (Certificate)ASN1Util.decode(Certificate.getTemplate(), certs[i].getEncoded()); CertificateInfo info = cert.getInfo(); OBJECT_IDENTIFIER sigalg = info.getSignatureAlgId().getOID(); System.out.println("Signature oid " + info.getSignatureAlgId().getOID()); SEQUENCE extensions = info.getExtensions(); for (int j = 0; j < extensions.size(); j++) { Extension ext = (Extension)extensions.elementAt(i); OBJECT_IDENTIFIER oid = ext.getExtnId(); OCTET_STRING value = ext.getExtnValue(); System.out.println("Extension " + oid.toString()); if (ext.getCritical()) { System.out.println("Critical extension: " + oid.toString()); } else { System.out.println("NON Critical extension: " + oid.toString()); } } System.out.println("Convert to JDK cert"); //Convert to JDK certificate CertificateFactory cf = CertificateFactory.getInstance("X.509"); ByteArrayInputStream bais = new ByteArrayInputStream( certs[i].getEncoded()); java.security.cert.X509Certificate jdkCert = (java.security.cert.X509Certificate) cf.generateCertificate(bais); bais.close(); System.out.println("Subject " + jdkCert.getSubjectDN()); System.out.println("Signature oid " + jdkCert.getSigAlgName()); /* non critical extensions */ Set nonCritSet = jdkCert.getNonCriticalExtensionOIDs(); if (nonCritSet != null && !nonCritSet.isEmpty()) { for (Iterator j = nonCritSet.iterator(); j.hasNext();) { String oid = j.next(); System.out.println(oid); } } else { System.out.println("no NON Critical Extensions"); } /* critical extensions */ Set critSet = jdkCert.getCriticalExtensionOIDs(); if (critSet != null && !critSet.isEmpty()) { System.out.println("Set of critical extensions:"); for (Iterator j = critSet.iterator(); j.hasNext();) { String oid = j.next(); System.out.println(oid); } } else { System.out.println("no Critical Extensions"); } } System.out.println("END"); } catch( Exception e ) { e.printStackTrace(); System.exit(1); } System.exit(0); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/PK10Gen.java000066400000000000000000000050641412550063600231600ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.util.Password; public class PK10Gen { public static void main(String args[]) { CryptoManager manager; Password pass1=null, pass2=null; char[] passchar1 = {'f', 'o', 'o', 'b', 'a', 'r'}; char[] passchar2 = {'n', 'e', 't', 's', 'c', 'a', 'p', 'e'}; if(args.length != 2) { System.err.println("Usage: java org.mozilla.jss.PK10Gen [rsa|dsa]"); return; } try { CryptoManager.initialize(args[0]); /* CryptoManager.initialize("secmod.db", "key3.db", "cert7.db"); CryptoManager cm = CryptoManager.getInstance(); PK11Token token = (PK11Token)cm.getInternalCryptoToken(); */ /* InitializationValues vals = new InitializationValues( args[0]+"/secmodule.db", args[0]+"/key3.db", args[0]+"/cert7.db"); CryptoManager.initialize(vals); */ try { manager = CryptoManager.getInstance(); } catch( NotInitializedException e ) { System.out.println("CryptoManager not initialized"); return; } CryptoToken token = manager.getInternalKeyStorageToken(); if(token.isLoggedIn() == false) { System.out.println("Good, isLoggedIn correctly says we're"+ " not logged in"); } else { System.out.println("ERROR: isLoggedIn incorrectly says we're"+ " logged in"); } pass1 = new Password( passchar1.clone()); pass2 = new Password( new char[]{0} ); token.initPassword(pass2, pass1); pass1.clear(); pass2.clear(); System.out.println("initialized PIN"); token.login(pass1); System.out.println("logged in"); String blob = token.generateCertRequest("cn=christina Fu", 512, args[1], (byte[]) null, (byte[]) null, (byte[]) null); System.out.println("pkcs#10 blob = \n" + blob); } catch(Exception e) { System.out.println("exception caught in PK10Gen: " + e.getMessage()); e.printStackTrace(); System.exit(1); } System.exit(0); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/PrintableConverterTest.java000066400000000000000000000065521412550063600265260ustar00rootroot00000000000000package org.mozilla.jss.tests; import org.junit.Assert; import org.junit.Test; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.x509.PrintableConverter; public class PrintableConverterTest { @Test public void testEmptyString() throws Exception { String string = ""; System.out.println("Converting: [" + string + "]"); byte[] expected = JSSUtil.encode(DerValue.tag_PrintableString, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = ConverterTestUtil.convert(new PrintableConverter(), string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testNullCharacters() throws Exception { String string = StringTestUtil.NULL_CHARS; System.out.println("Converting: [" + StringTestUtil.toString(string.getBytes()) + "]"); System.out.println(" - expected: IllegalArgumentException"); try { byte[] actual = ConverterTestUtil.convert(new PrintableConverter(), string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.fail(); } catch (Exception e) { System.out.println(" - actual : " + e.getClass().getSimpleName()); Assert.assertTrue(e instanceof IllegalArgumentException); } } @Test public void testPrintableCharacters() throws Exception { String string = StringTestUtil.PRINTABLE_CHARS; System.out.println("Converting: [" + string + "]"); byte[] expected = JSSUtil.encode(DerValue.tag_PrintableString, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = ConverterTestUtil.convert(new PrintableConverter(), string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testControlCharacters() throws Exception { String string = StringTestUtil.CONTROL_CHARS; System.out.println("Converting: [" + StringTestUtil.toString(string.getBytes()) + "]"); System.out.println(" - expected: IllegalArgumentException"); try { byte[] actual = ConverterTestUtil.convert(new PrintableConverter(), string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.fail(); } catch (Exception e) { System.out.println(" - actual : " + e.getClass().getSimpleName()); Assert.assertTrue(e instanceof IllegalArgumentException); } } @Test public void testMultibyteCharacters() throws Exception { String string = StringTestUtil.MULTIBYTE_CHARS; System.out.println("Converting: [" + string + "]"); System.out.println(" - expected: IllegalArgumentException"); try { byte[] actual = ConverterTestUtil.convert(new PrintableConverter(), string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.fail(); } catch (Exception e) { System.out.println(" - actual : " + e.getClass().getSimpleName()); Assert.assertTrue(e instanceof IllegalArgumentException); } } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/PrintableStringTest.java000066400000000000000000000214341412550063600260210ustar00rootroot00000000000000package org.mozilla.jss.tests; import java.io.IOException; import org.junit.Assert; import org.junit.Test; import org.mozilla.jss.netscape.security.util.DerValue; public class PrintableStringTest { public byte tag = DerValue.tag_PrintableString; @Test public void testEncodingEmptyString() throws Exception { String string = ""; System.out.println("Encoding: [" + string + "]"); byte[] expected = JSSUtil.encode(tag, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testDecodingEmptyString() throws Exception { String input = ""; byte[] data = JSSUtil.encode(tag, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: [" + input + "]"); String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + output + "]"); Assert.assertEquals(input, output); } @Test public void testEncodingNullCharacters() throws Exception { String string = StringTestUtil.NULL_CHARS; System.out.println("Encoding: [" + StringTestUtil.toString(string.getBytes()) + "]"); System.out.println(" - expected: IOException"); try { byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.fail(); } catch (Exception e) { System.out.println(" - actual : " + e.getClass().getSimpleName()); Assert.assertTrue(e instanceof IOException); } } @Test public void testDecodingNullCharacters() throws Exception { byte[] data = { 0x13, 0x01, 0x00 }; System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); String expected = ""; // skip null chars (bug 359010) System.out.println(" - expected: [" + expected + "]"); String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + output + "]"); Assert.assertEquals(expected, output); } @Test public void testEncodingPrintableCharacters() throws Exception { String string = StringTestUtil.PRINTABLE_CHARS; System.out.println("Encoding: [" + string + "]"); byte[] expected = JSSUtil.encode(tag, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testDecodingPrintableCharacters() throws Exception { String input = StringTestUtil.PRINTABLE_CHARS; byte[] data = JSSUtil.encode(tag, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: [" + input + "]"); String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + output + "]"); Assert.assertEquals(input, output); } @Test public void testEncodingNonPrintableCharacters() throws Exception { String string = StringTestUtil.NON_PRINTABLE_CHARS; System.out.println("Encoding: [" + StringTestUtil.toString(string.getBytes()) + "]"); System.out.println(" - expected: IOException"); try { byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.fail(); } catch (Exception e) { System.out.println(" - actual : " + e.getClass().getSimpleName()); Assert.assertTrue(e instanceof IOException); } } @Test public void testDecodingNonPrintableCharacters() throws Exception { String input = StringTestUtil.NON_PRINTABLE_CHARS; byte[] data = JSSUtil.encode(DerValue.tag_UTF8String, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: IOException"); try { String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + StringTestUtil.toString(output.getBytes()) + "]"); Assert.fail(); } catch (Exception e) { System.out.println(" - actual : " + e.getClass().getSimpleName()); Assert.assertTrue(e instanceof IOException); } } @Test public void testEncodingControlCharacters() throws Exception { String string = StringTestUtil.CONTROL_CHARS; System.out.println("Encoding: [" + StringTestUtil.toString(string.getBytes()) + "]"); System.out.println(" - expected: IOException"); try { byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.fail(); } catch (Exception e) { System.out.println(" - actual : " + e.getClass().getSimpleName()); Assert.assertTrue(e instanceof IOException); } } @Test public void testDecodingControlCharacters() throws Exception { String input = StringTestUtil.CONTROL_CHARS; byte[] data = JSSUtil.encode(DerValue.tag_UTF8String, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: IOException"); try { String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + StringTestUtil.toString(output.getBytes()) + "]"); Assert.fail(); } catch (Exception e) { System.out.println(" - actual : " + e.getClass().getSimpleName()); Assert.assertTrue(e instanceof IOException); } } @Test public void testEncodingMultibyteCharacters() throws Exception { String string = StringTestUtil.MULTIBYTE_CHARS; System.out.println("Encoding: [" + string + "]"); System.out.println(" - expected: IOException"); try { byte[] actual = StringTestUtil.encode(tag, StringTestUtil.MULTIBYTE_CHARS); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.fail(); } catch (Exception e) { System.out.println(" - actual : " + e.getClass().getSimpleName()); Assert.assertTrue(e instanceof IOException); } } @Test public void testDecodingMultibyteCharacters() throws Exception { String input = StringTestUtil.MULTIBYTE_CHARS; byte[] data = JSSUtil.encode(DerValue.tag_UTF8String, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: IOException"); try { String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + StringTestUtil.toString(output.getBytes()) + "]"); Assert.fail(); } catch (Exception e) { System.out.println(" - actual : " + e.getClass().getSimpleName()); Assert.assertTrue(e instanceof IOException); } } @Test public void testEncodingTime() throws Exception { System.out.println("Encoding time:"); String string = StringTestUtil.PRINTABLE_CHARS; long t0 = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) JSSUtil.encode(tag, string); long t1 = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) StringTestUtil.encode(tag, string); long t2 = System.currentTimeMillis(); long time1 = t1 - t0; long time2 = t2 - t1; System.out.println(" - JSS : " + time1 + " ms"); System.out.println(" - Internal: " + time2 + " ms"); } @Test public void testDecodingTime() throws Exception { System.out.println("Decoding time:"); String string = StringTestUtil.PRINTABLE_CHARS; byte[] data = JSSUtil.encode(tag, string); long t0 = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) JSSUtil.decode(tag, data); long t1 = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) StringTestUtil.decode(tag, data); long t2 = System.currentTimeMillis(); long time1 = t1 - t0; long time2 = t2 - t1; System.out.println(" - JSS : " + time1 + " ms"); System.out.println(" - Internal: " + time2 + " ms"); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/README_bbenv000066400000000000000000000043651412550063600232470ustar00rootroot00000000000000# This file has been renamed to "jss/org/mozilla/jss/tests/README_bbenv", and # the build/test procedure documented below has been replaced; the new build/test # procedure has been documented in top-level "jss/README". Procedure for building nspr/nss/jss and testing jss by using the provided sample run and bbenv scripts located in the jss/org/mozilla/jss/tests directory: 1. Create working directories: % mkdir -p work4jss/hg 2. Checkout all the needed sources: % cd work4jss/hg % hg clone https://hg.mozilla.org/projects/nspr % hg clone https://hg.mozilla.org/projects/nss % hg clone https://hg.mozilla.org/projects/jss % cd .. 3. Copy runSample.sh renaming it to run.sh: % cp hg/jss/org/mozilla/jss/tests/runSample.sh run.sh 4. Copy bbenvSample.sh renaming it to bbenv.sh: % cp hg/jss/org/mozilla/jss/tests/bbenvSample.sh bbenv.sh 5. Edit bbenv.sh to comply with the system that is being tested: (a) Set/reset the DOMSUF variable so that it can be resolved locally: NOTE: By default, DOMSUF=localdomain is set. (b) Set/reset the JAVA_HOME_64 variable in the bbenv script accordingly: On Linux (e. g. - Fedora 25), update java-1.8.0-openjdk to the latest and then run sudo /usr/sbin/alternatives --config java and hit enter. To check/select your Java version on Linux: % sudo /usr/sbin/alternatives --config java There is 1 program that provides 'java'. Selection Command ----------------------------------------------- *+ 1 java-1.8.0-openjdk.x86_64 (/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.111-3.b16.fc25.x86_64/jre/bin/java) Enter to keep the current selection[+], or type selection number: NOTE: You may have multiple entries (like on RHEl-7.x) or only one. Per this example, set: JAVA_HOME_64=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.111-3.b16.fc25.x86_64 Alternatively, on macOS, you'll have something like this: JAVA_HOME_64=/Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home 6. Build nspr, nss, and jss and run the jss tests: % run.sh 1> run.log 2>&1 7. View the results captured in the various log files, for example: % less run.log % less output/all.log % less output/tmp.log jss-5.0.0/src/test/java/org/mozilla/jss/tests/SDR.java000066400000000000000000000035411412550063600225010ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.SecretDecoderRing; import org.mozilla.jss.util.ConsolePasswordCallback; public class SDR { public static void main(String[] args) { try { String cmd = args[0]; String infile = args[1]; String outfile = args[2]; CryptoManager cm = CryptoManager.getInstance(); CryptoToken token = cm.getInternalKeyStorageToken(); token.login(new ConsolePasswordCallback()); SecretDecoderRing sdr = new SecretDecoderRing(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); int numread; byte[] data = new byte[1024]; try (FileInputStream fis = new FileInputStream(infile)) { while ((numread = fis.read(data)) != -1) { bos.write(data, 0, numread); } } byte[] inputBytes = bos.toByteArray(); byte[] outputBytes; if( cmd.equalsIgnoreCase("encrypt") ) { outputBytes = sdr.encrypt(inputBytes); } else { outputBytes = sdr.decrypt(inputBytes); } try (FileOutputStream fos = new FileOutputStream(outfile)) { fos.write(outputBytes); } } catch(Exception e) { e.printStackTrace(); System.exit(1); } System.exit(0); } private static char[] hex = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; } jss-5.0.0/src/test/java/org/mozilla/jss/tests/SSLClientAuth.java000066400000000000000000000416731412550063600245030ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.security.cert.CertificateEncodingException; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NicknameConflictException; import org.mozilla.jss.UserCertConflictException; import org.mozilla.jss.ssl.*; import org.mozilla.jss.crypto.*; import org.mozilla.jss.asn1.*; import org.mozilla.jss.pkix.primitive.*; import org.mozilla.jss.pkix.cert.*; import org.mozilla.jss.pkix.cert.Certificate; import org.mozilla.jss.util.PasswordCallback; import java.util.Calendar; import java.util.Date; import java.security.*; import java.security.PrivateKey; import java.io.*; import java.net.SocketException; /** * SSLClientAuth Server/client test. */ public class SSLClientAuth implements Runnable { private CryptoManager cm; public static final SignatureAlgorithm sigAlg = SignatureAlgorithm.RSASignatureWithSHA256Digest; /** * Method that generates a certificate for given credential * * @param issuerName * @param subjectName * @param serialNumber * @param privKey * @param pubKey * @param rand * @param extensions * @throws java.lang.Exception * @return Certificate */ public static Certificate makeCert(String issuerName, String subjectName, int serialNumber, PrivateKey privKey, PublicKey pubKey, int rand, SEQUENCE extensions) throws Exception { AlgorithmIdentifier sigAlgID = new AlgorithmIdentifier( sigAlg.toOID()); Name issuer = new Name(); issuer.addCountryName("US"); issuer.addOrganizationName("Mozilla"); issuer.addOrganizationalUnitName("JSS Testing" + rand); issuer.addCommonName(issuerName); Name subject = new Name(); subject.addCountryName("US"); subject.addOrganizationName("Mozilla"); subject.addOrganizationalUnitName("JSS Testing" + rand); subject.addCommonName(subjectName); Calendar cal = Calendar.getInstance(); Date notBefore = cal.getTime(); cal.add(Calendar.YEAR, 1); Date notAfter = cal.getTime(); SubjectPublicKeyInfo.Template spkiTemp = new SubjectPublicKeyInfo.Template(); SubjectPublicKeyInfo spki = (SubjectPublicKeyInfo) ASN1Util.decode(spkiTemp, pubKey.getEncoded()); CertificateInfo info = new CertificateInfo( CertificateInfo.v3, new INTEGER(serialNumber), sigAlgID, issuer, notBefore, notAfter, subject, spki); if( extensions != null ) { info.setExtensions(extensions); } return new Certificate(info, privKey, sigAlg); } /** * * @param args * @throws java.lang.Exception */ public static void main(String[] args) throws Exception { (new SSLClientAuth()).doIt(args); } private X509Certificate nssServerCert, nssClientCert; private String serverCertNick, clientCertNick; /** * * @param args * @throws java.lang.Exception */ public void doIt(String[] args) throws Exception { if ( args.length < 2 ) { System.out.println("Usage: java org.mozilla.jss.tests." + "SSLClientAuth [port]" + " [Certificate Serial Number]"); System.exit(1); } cm = CryptoManager.getInstance(); CryptoToken tok = cm.getInternalKeyStorageToken(); PasswordCallback cb = new FilePasswordCallback(args[1]); tok.login(cb); if (args.length >= 3) { port = Integer.parseInt(args[2]); System.out.println("using port:" + port); } if (args.length >= 4) { serialNum = Integer.parseInt(args[3]); } else { SecureRandom rng= SecureRandom.getInstance("pkcs11prng", "Mozilla-JSS"); serialNum = nextRandInt(rng); } X509Certificate[] certs; /* ensure certificate does not already exists */ /* we don't have to test all three */ serverCertNick = "SSLserver-"+serialNum; clientCertNick = "SSLclient-"+serialNum; certs = cm.findCertsByNickname(serverCertNick); if (certs.length == 0) { generateCerts(cm, serialNum); } else { try { nssServerCert = cm.findCertByNickname(serverCertNick); nssClientCert = cm.findCertByNickname(clientCertNick); } catch (TokenException ex) { ex.printStackTrace(); System.exit(1); } catch (ObjectNotFoundException ex) { ex.printStackTrace(); System.exit(1); } } configureDefaultSSLoptions(); testSpecificCiphers(); useNickname = false; testConnection(); useNickname = true; testConnection(); System.out.println("Exiting main()"); if( getSuccess() ) { System.exit(0); } else { System.exit(1); } } private boolean useNickname; private void generateCerts(CryptoManager cm, int serialNum) { // RSA Key with default exponent int keyLength = 4096; try { java.security.KeyPairGenerator kpg = java.security.KeyPairGenerator.getInstance("RSA", "Mozilla-JSS"); kpg.initialize(keyLength); KeyPair caPair = kpg.genKeyPair(); //Generate CA cert SEQUENCE extensions = new SEQUENCE(); extensions.addElement(makeBasicConstraintsExtension()); Certificate caCert = makeCert("CACert", "CACert", serialNum, caPair.getPrivate(), caPair.getPublic(), serialNum, extensions); X509Certificate nssCaCert = cm.importUserCACertPackage( ASN1Util.encode(caCert), "SSLCA-"+serialNum); InternalCertificate intern = (InternalCertificate)nssCaCert; intern.setSSLTrust( InternalCertificate.TRUSTED_CA | InternalCertificate.TRUSTED_CLIENT_CA | InternalCertificate.VALID_CA); // generate server cert kpg.initialize(keyLength); KeyPair serverPair = kpg.genKeyPair(); Certificate serverCert = makeCert("CACert", "localhost", serialNum+1, caPair.getPrivate(), serverPair.getPublic(), serialNum, null); nssServerCert = cm.importCertPackage( ASN1Util.encode(serverCert), serverCertNick); // generate client auth cert kpg.initialize(keyLength); KeyPair clientPair = kpg.genKeyPair(); Certificate clientCert = makeCert("CACert", "ClientCert", serialNum+2, caPair.getPrivate(), clientPair.getPublic(), serialNum, null); nssClientCert = cm.importCertPackage( ASN1Util.encode(clientCert), clientCertNick); } catch (CertificateEncodingException ex) { ex.printStackTrace(); System.exit(1); } catch (NoSuchAlgorithmException ex) { ex.printStackTrace(); System.exit(1); } catch (NoSuchProviderException ex) { ex.printStackTrace(); System.exit(1); } catch (NicknameConflictException ex) { ex.printStackTrace(); System.exit(1); } catch (UserCertConflictException ex) { ex.printStackTrace(); System.exit(1); } catch (TokenException ex) { ex.printStackTrace(); System.exit(1); } catch (NoSuchItemOnTokenException ex) { ex.printStackTrace(); System.exit(1); } catch (Exception ex) { ex.printStackTrace(); System.exit(1); } } private void configureDefaultSSLoptions() { try { //Disable SSL2 and SSL3 ciphers SSLSocket.enableSSL2Default(false); SSLSocket.enableSSL3Default(false); /* TLS is enabled by default */ SSLSocket.setSSLVersionRangeDefault(SSLProtocolVariant.STREAM, new SSLVersionRange(SSLVersionRange.tls1_2, SSLVersionRange.tls1_2)); /* Enable Session tickets by default */ SSLSocket.enableSessionTicketsDefault(true); /* if FIPS is enabled, configure only FIPS ciphersuites */ if (cm.FIPSEnabled()) { System.out.println("The NSS database is configured in FIPS" + "mode."); System.out.println("Enable ony FIPS ciphersuites."); int ciphers[] = org.mozilla.jss.ssl.SSLSocket.getImplementedCipherSuites(); for (int i = 0; i < ciphers.length; ++i) { if (SSLSocket.isFipsCipherSuite(ciphers[i])) { /* enable the FIPS ciphersuite */ SSLSocket.setCipherPreferenceDefault(ciphers[i], true); } else if (SSLSocket.getCipherPreferenceDefault( ciphers[i])) { /* disable the non fips ciphersuite */ SSLSocket.setCipherPreferenceDefault(ciphers[i], false); } } } } catch (SocketException ex) { System.out.println("Error configuring default SSL options."); ex.printStackTrace(); System.exit(1); } } // test one or more specific ciphers // -- normally for newly added ciphers private void testSpecificCiphers() { try { //Disable SSL2 and SSL3 ciphers SSLSocket.enableSSL2Default(false); SSLSocket.enableSSL3Default(false); /* TLS is enabled by default */ /* Enable Session tickets by default */ SSLSocket.enableSessionTicketsDefault(true); /* * when testing specific ciphers: * 1. flip this to true * 2. change the ciphers comparison (the code below was from * the latest test */ if (false) { System.out.println("testing new TLS_*SHA384 ciphers"); System.out.println("Enable ony two new ciphers."); int ciphers[] = org.mozilla.jss.ssl.SSLSocket.getImplementedCipherSuites(); for (int i = 0; i < ciphers.length; ++i) { if (ciphers[i] == 157 || ciphers[i] == 159) { System.out.println("enabling cipher: " + ciphers[i]); /* enable a couple SHA384 ciphers */ SSLSocket.setCipherPreferenceDefault(ciphers[i], true); } else { System.out.println("disabling cipher: " + ciphers[i]); /* disable the non SHA384 ciphers */ SSLSocket.setCipherPreferenceDefault(ciphers[i], false); } } } } catch (SocketException ex) { System.out.println("Error configuring ciphers."); ex.printStackTrace(); System.exit(1); } } private void testConnection() throws Exception { serverReady = false; // spawn server Thread server = new Thread(this); server.start(); // wait for server to open its socket synchronized(this) { while(!serverReady) { this.wait(); } } // connect to the server System.out.println("client about to connect"); SSLSocket sock = new SSLSocket("localhost", port); if( useNickname ) { sock.setClientCertNickname(clientCertNick); System.out.println("Client specified cert by nickname"); } else { sock.setClientCert(nssClientCert); System.out.println("Client specified cert directly"); } System.out.println("client connected"); sock.addHandshakeCompletedListener( new HandshakeListener("client",this)); // force the handshake sock.forceHandshake(); String cipher = sock.getStatus().getCipher(); System.out.println("client forced handshake. ciphersuite: " + cipher); sock.close(); // wait for the server to finish server.join(); } public static class HandshakeListener implements SSLHandshakeCompletedListener { private String who; private SSLClientAuth boss; public HandshakeListener(String who, SSLClientAuth boss) { this.who = who; this.boss = boss; } @Override public void handshakeCompleted(SSLHandshakeCompletedEvent event) { try { String mesg = who + " got a completed handshake "; SSLSecurityStatus status = event.getStatus(); if( status.isSecurityOn() ) { mesg += "(security is ON)"; } else { mesg += "(security is OFF)"; } System.out.println(mesg); } catch(Exception e) { e.printStackTrace(); boss.setFailure(); } } } public synchronized void setFailure() { success = false; } public synchronized boolean getSuccess() { return success; } private boolean success = true; public int port = 29752; public int serialNum = 0; public boolean serverReady = false; /** * Server run method. */ @Override public void run() { try { // We have to configure the server session ID cache before // creating any server sockets. SSLServerSocket.configServerSessionIDCache(10, 100, 100, null); // open the server socket and bind to the port System.out.println("Server about to create socket"); SSLServerSocket serverSock = new SSLServerSocket(port, 5, null, null, true); System.out.println("Server created socket"); serverSock.requireClientAuth(SSLSocket.SSL_REQUIRE_NO_ERROR); if( useNickname ) { serverSock.setServerCertNickname(serverCertNick); System.out.println("Server specified cert by nickname"); } else { serverSock.setServerCert(nssServerCert); System.out.println("Server specified cert directly"); } // tell the client we're ready synchronized(this) { serverReady = true; this.notify(); } // accept the connection System.out.println("Server about to accept"); SSLSocket sock = (SSLSocket) serverSock.accept(); System.out.println("Server accepted"); sock.addHandshakeCompletedListener( new HandshakeListener("server", this)); // try to read some bytes, to allow the handshake to go through InputStream is = sock.getInputStream(); try { System.out.println("Server about to read"); is.read(); System.out.println("Server read successful"); } catch(EOFException e) { System.out.println("Server got EOF"); } sock.close(); serverSock.close(); } catch(Exception e) { synchronized(this) { serverReady = true; setFailure(); this.notify(); } e.printStackTrace(); } System.out.println("Server exiting"); } static Extension makeBasicConstraintsExtension() throws Exception { SEQUENCE bc = new SEQUENCE(); bc.addElement( new BOOLEAN(true) ); // cA OBJECT_IDENTIFIER bcOID = new OBJECT_IDENTIFIER( new long[] {2, 5, 29, 19}); // from RFC 2459 OCTET_STRING enc = new OCTET_STRING(ASN1Util.encode(bc)); return new Extension(bcOID, true, enc); } static int nextRandInt(SecureRandom rand) throws Exception { int i; byte[] bytes = new byte[4]; rand.nextBytes(bytes); i = ((int)bytes[0])<<24 | ((int)bytes[1])<<16 | ((int)bytes[2])<<8 | ((int)bytes[3]); System.out.println("generated random value:" + i); return i; } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/SelfTest.java000066400000000000000000000170341412550063600236040ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.util.Enumeration; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NoSuchTokenException; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.crypto.AlreadyInitializedException; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.TokenException; import org.mozilla.jss.pkcs11.PK11Module; import org.mozilla.jss.pkcs11.PK11Token; import org.mozilla.jss.util.IncorrectPasswordException; import org.mozilla.jss.util.Password; public class SelfTest { public static void main(String[] args) throws Throwable { CryptoToken tok; CryptoToken intTok; CryptoManager manager; Password pass1=null, pass2=null; java.security.KeyPair keyPair; char[] passchar1 = {'f', 'o', 'o', 'b', 'a', 'r'}; char[] passchar2 = {'n', 'e', 't', 's', 'c', 'a', 'p', 'e'}; if(args.length != 1) { System.err.println("Usage: java ...SelfTest "); return; } try { manager = CryptoManager.getInstance(); } catch( NotInitializedException e ) { System.out.println("CryptoManager not initialized"); return; } try { tok = manager.getTokenByName("asdffda"); System.out.println("ERROR: found a nonexistent token"); } catch (NoSuchTokenException e) { System.out.println("Good, could not find non-existent token"); } try { Enumeration modules = manager.getModules(); System.out.println("Modules:"); while(modules.hasMoreElements()) { System.out.println("\t"+ modules.nextElement().getName() ); } Enumeration tokens = manager.getAllTokens(); System.out.println("All Tokens:"); while(tokens.hasMoreElements()) { System.out.println("\t"+ tokens.nextElement().getName() ); } Enumeration extTokens = manager.getExternalTokens(); System.out.println("External Tokens:"); while(extTokens.hasMoreElements()) { System.out.println("\t"+ extTokens.nextElement().getName() ); } tok = manager.getTokenByName("Internal Key Storage Token"); System.out.println("Good, found internal DB token"); if( tok.equals(manager.getInternalKeyStorageToken()) ) { System.out.println("Good, it really is the key storage token"); } else { System.out.println("ERROR: it's not the same as the key "+ "storage token!"); } if( ((PK11Token)tok).isInternalKeyStorageToken() ) { System.out.println("Good, "+tok.getName()+" knows "+ "what it is"); } else { System.out.println("ERROR: "+tok.getName()+" doesn't know"+ " it is key storage token"); } intTok = manager.getInternalCryptoToken(); if( ((PK11Token)intTok).isInternalCryptoToken() ) { System.out.println("Good, "+tok.getName()+ " knows it is the internal token"); } else { System.out.println("ERROR: "+tok.getName()+ " doesn't know what that it is the internal token"); } if(tok.isLoggedIn() == false) { System.out.println("Good, isLoggedIn correctly says we're"+ " not logged in"); } else { System.out.println("ERROR: isLoggedIn incorrectly says we're"+ " logged in"); } System.out.println("Good, successfully opened token \""+ tok.getName()+"\""); pass1 = new Password( passchar1.clone()); pass2 = new Password( new char[]{0} ); tok.initPassword(pass2, pass1); pass1.clear(); pass2.clear(); System.out.println("Good, initialized PIN"); tok.logout(); try { pass1 = new Password( passchar2.clone()); tok.login(pass1); System.out.println("ERROR: Successfully logged in with wrong"+ " PIN"); } catch (IncorrectPasswordException e) { System.out.println("Good, unable to login with wrong PIN"); } finally { pass1.clear(); } pass1 = new Password( passchar1.clone()); tok.login(pass1); pass1.clear(); System.out.println("Good, logged in"); if(tok.isLoggedIn() == true) { System.out.println("Good, isLoggedIn correctly says we're"+ " logged in"); } else { System.out.println("ERROR: isLoggedIn incorrectly says we're"+ " not logged in"); } pass1 = new Password( passchar1.clone()); pass2 = new Password( passchar2.clone()); tok.changePassword(pass1, pass2); pass1.clear(); pass2.clear(); System.out.println("Good, changed PIN"); try { pass1 = new Password( passchar1.clone()); tok.login(pass1); // Should still be logged in System.out.println("Good, logging in with wrong PIN ok if "+ " already logged in"); } catch (IncorrectPasswordException e) { System.out.println("ERROR: logged in second time with wrong"+ "PIN, but we should still be logged in"); } finally { pass1.clear(); } try { tok.logout(); System.out.println("Good, logged out successfully."); } catch (TokenException e) { System.out.println("ERROR: failed to logout from token"); } if(tok.isLoggedIn() == false) { System.out.println("Good, isLoggedIn correctly says we're"+ " not logged in"); } else { System.out.println("ERROR: isLoggedIn incorrectly says we're"+ " logged in"); } try { tok.logout(); System.out.println("ERROR: logged out twice in a row"); } catch (TokenException e) { System.out.println("Good, got an exception when we tried"+ " to log out twice in a row"); } try { pass1 = new Password( passchar1.clone()); tok.login(pass1); pass1.clear(); System.out.println("ERROR: logged in with wrong pw"); } catch (IncorrectPasswordException e) { System.out.println("Good, logging in with wrong PIN gave err"); } System.out.println("Test completed"); tok = null; } catch (IncorrectPasswordException e) { System.out.println("Got an incorrect PIN: "+e); } catch (AlreadyInitializedException e) { System.out.println( "ERROR: This test only works with uninitialized databases"); } catch (TokenException e) { System.out.println("Token error: " + e); } catch (NoSuchTokenException e) { System.out.println("ERROR: could not find internal DB token"); } finally { if(pass1 != null) { pass1.clear(); } if(pass2 != null) { pass2.clear(); } } //System.gc(); //NativeProxy.assertRegistryEmpty(); //System.runFinalization(); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/SetupDBs.java000066400000000000000000000032601412550063600235400ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import org.mozilla.jss.*; import org.mozilla.jss.crypto.*; import org.mozilla.jss.util.*; /** * Create the NSS databases * **/ public class SetupDBs { public static void main(String args[]) throws Exception { if (args.length != 2) { System.err.println("Usage: java org.mozilla.jss.tests.SetupDBs " + " \n" + "Password file should have format:\n " + "Internal\\ Key\\ Storage\\ Token=m1oZilla\n " + "NSS\\ FIPS\\ 140-2\\ User\\ Private\\ " + "Key=m1oZilla\n"); System.exit(1); } // Initialize JSS, preferring the local CryptoManager initialization // over the one from java.security. InitializationValues ivs = new InitializationValues(args[0]); CryptoManager.initialize(ivs); CryptoManager cm = CryptoManager.getInstance(); // Get the internal key storage token so we can set the password. CryptoToken tok = cm.getInternalKeyStorageToken(); // Set the user password to the one from the password file; the // security officer password is empty. PasswordCallback securityOfficerPassword = new NullPasswordCallback(); PasswordCallback userPassword = new FilePasswordCallback(args[1]); tok.initPassword(securityOfficerPassword, userPassword); cm.shutdown(); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/SigTest.java000066400000000000000000000107031412550063600234310ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* This program demonstrates how to sign data with keys from JSS * * The token name can be either the name of a hardware token, or * one of the internal tokens: * Internal Crypto Services Token * Internal Key Storage Token (keys stored in key4.db) */ package org.mozilla.jss.tests; import java.security.KeyPair; import java.security.PublicKey; import java.util.Enumeration; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.KeyPairAlgorithm; import org.mozilla.jss.crypto.KeyPairGenerator; import org.mozilla.jss.crypto.KeyPairGeneratorSpi; import org.mozilla.jss.crypto.Policy; import org.mozilla.jss.crypto.Signature; import org.mozilla.jss.crypto.SignatureAlgorithm; import org.mozilla.jss.pkcs11.PK11Token; public class SigTest { public static void usage() { System.out.println( "Usage: java org.mozilla.jss.crypto.SigTest " + " [tokenname]"); } public static void main(String args[]) throws Exception { CryptoToken token; CryptoManager manager; byte[] data = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9}; byte[] signature; Signature signer; Signature signerPSS; PublicKey pubk; KeyPairGenerator kpgen; KeyPair keyPair; if (args.length < 2 || args.length > 3) { usage(); System.exit(1); } manager = CryptoManager.getInstance(); manager.setPasswordCallback(new FilePasswordCallback(args[1])); /* Print out list of available tokens */ Enumeration en = manager.getAllTokens(); System.out.println("Available tokens:"); while (en.hasMoreElements()) { PK11Token p = (PK11Token) en.nextElement(); System.out.println(" token : " + p.getName()); } if (args.length >= 3) { token = manager.getTokenByName(args[2]); } else { //get default internal key storage token token = manager.getInternalKeyStorageToken(); } // Generate an RSA keypair kpgen = token.getKeyPairGenerator(KeyPairAlgorithm.RSA); kpgen.initialize(Policy.RSA_MINIMUM_KEY_SIZE); KeyPairGeneratorSpi.Usage usages[] = { KeyPairGeneratorSpi.Usage.SIGN, KeyPairGeneratorSpi.Usage.VERIFY}; KeyPairGeneratorSpi.Usage usages_mask[] = { KeyPairGeneratorSpi.Usage.SIGN, KeyPairGeneratorSpi.Usage.VERIFY}; kpgen.setKeyPairUsages(usages, usages_mask); keyPair = kpgen.genKeyPair(); // RSA SHA256 signer = token.getSignatureContext( SignatureAlgorithm.RSASignatureWithSHA256Digest); System.out.println("Created a signing context"); signer.initSign( (org.mozilla.jss.crypto.PrivateKey) keyPair.getPrivate()); System.out.println("initialized the signing operation"); signer.update(data); System.out.println("updated signature with data"); signature = signer.sign(); System.out.println("Successfully signed!"); signer.initVerify(keyPair.getPublic()); System.out.println("initialized verification"); signer.update(data); System.out.println("updated verification with data"); if (signer.verify(signature)) { System.out.println("Signature Verified Successfully!"); } else { throw new Exception("ERROR: Signature failed to verify."); } signerPSS = token.getSignatureContext( SignatureAlgorithm.RSAPSSSignatureWithSHA256Digest); signerPSS.initSign( (org.mozilla.jss.crypto.PrivateKey) keyPair.getPrivate()); signerPSS.update(data); signature = signerPSS.sign(); System.out.println("PSS Successfully signed!"); signerPSS.initVerify(keyPair.getPublic()); signerPSS.update(data); System.out.println("updated verification with data"); if (signerPSS.verify(signature)) { System.out.println("PSS Signature Verified Successfully!"); } else { throw new Exception("ERROR: PSS Signature failed to verify."); } System.out.println("SigTest passed."); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/StringTestUtil.java000066400000000000000000000050651412550063600250200ustar00rootroot00000000000000package org.mozilla.jss.tests; import org.mozilla.jss.netscape.security.util.DerInputStream; import org.mozilla.jss.netscape.security.util.DerOutputStream; import org.mozilla.jss.netscape.security.util.DerValue; public class StringTestUtil { public final static String NULL_CHARS = "\u0000"; public final static String PRINTABLE_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 \'()+,-./:=?"; public final static String NON_PRINTABLE_CHARS = "\"\\"; public final static String CONTROL_CHARS = "\b\t\n\f\r"; public final static String MULTIBYTE_CHARS = "\u6211\u7231\u4F60"; // I love you public static String toString(byte[] array) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < array.length; i++) { if (i > 0) sb.append(" "); sb.append(Integer.toHexString(0xff & array[i] | 0x100).substring(1).toUpperCase()); } return sb.toString(); } public static byte[] normalizeUnicode(byte[] data) throws Exception { try (DerOutputStream os = new DerOutputStream()) { DerValue value = new DerValue(data); byte[] tmp = value.data.toByteArray(); if (tmp[0] == -2 && tmp[1] == -1) { // remove optional big-endian byte-order mark byte tag = value.tag; int length = value.length() - 2; os.putTag((byte) 0, false, tag); os.putLength(length); os.write(tmp, 2, length); return os.toByteArray(); } return data; } } public static byte[] encode(byte tag, String string) throws Exception { try (DerOutputStream os = new DerOutputStream()) { os.putStringType(tag, string); return os.toByteArray(); } } public static String decode(byte tag, byte[] bytes) throws Exception { DerInputStream is = new DerInputStream(bytes); switch (tag) { case DerValue.tag_BMPString: return is.getBMPString(); case DerValue.tag_IA5String: return is.getIA5String(); case DerValue.tag_PrintableString: return is.getPrintableString(); case DerValue.tag_T61String: return is.getT61String(); case DerValue.tag_UniversalString: return is.getUniversalString(); case DerValue.tag_UTF8String: return is.getDerValue().getUTF8String(); default: throw new Exception("Unsupported tag: " + tag); } } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/SymKeyDeriving.java000066400000000000000000000374401412550063600247670ustar00rootroot00000000000000/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * 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 Services for Java. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998-2000 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ package org.mozilla.jss.tests; import org.mozilla.jss.crypto.*; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.pkcs11.PKCS11Constants; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Enumeration; /** * Sym Key deriving tests.. * */ public class SymKeyDeriving { private static final byte[] iv8 = new byte [] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8 }; private static final byte[] iv16 = new byte [] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9,0xa, 0xb, 0xc,0xd,0xe, 0xf,0x10 }; private static final byte[] derivationData1 = new byte[] { 0x11, 0x11, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18 }; private static final byte[] derivationData2 = new byte [] { 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10 }; private static final byte[] derivationData16 = new byte[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6,0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10 }; public static void main(String args[]) throws Exception { if (args.length != 2) { System.err.println("Usage SymKeyDeriving /path/to/nssdb /path/to/password.txt"); System.exit(1); } SymmetricKey macKeyDev = null; CryptoManager cm = CryptoManager.getInstance(); cm.setPasswordCallback(new FilePasswordCallback(args[1])); CryptoToken token = cm.getInternalCryptoToken(); CryptoToken keyToken = cm.getInternalKeyStorageToken(); System.out.println("interal token name: " + keyToken.getName()); KeyGenerator keyKg = keyToken.getKeyGenerator(KeyGenAlgorithm.DES3); SymmetricKey baseKey = keyKg.generate(); KeyGenerator keyKgDes = keyToken.getKeyGenerator(KeyGenAlgorithm.DES); SymmetricKey baseKeyDes = keyKgDes.generate(); System.out.println("strength: " + baseKeyDes.getStrength()); KeyGenerator keyKgAES = keyToken.getKeyGenerator(KeyGenAlgorithm.AES); keyKgAES.initialize(128); SymmetricKey baseKeyAES = keyKgAES.generate(); System.out.println("baseKey bytes: "); byte[] baseBytes = baseKey.getEncoded(); displayByteArray(baseBytes,true); /*****************************************************************************************************/ System.out.println("\n Mechanism CKM_EXTRACT_KEY_FROM_KEY test 16 bytes. \n"); SymmetricKeyDeriver deriver = token.getSymmetricKeyDeriver(); System.out.println("deriver: " + deriver); System.out.println("CKM_EXTRACT_KEY_FROM_KEY : " + PKCS11Constants.CKM_EXTRACT_KEY_FROM_KEY); long bitPosition = 0; byte[] param = longToBytes(bitPosition); deriver.initDerive( baseKey, PKCS11Constants.CKM_EXTRACT_KEY_FROM_KEY,param,null, PKCS11Constants.CKA_ENCRYPT, PKCS11Constants.CKA_DERIVE,(long) 16); SymmetricKey extracted16 = deriver.derive(); System.out.println("Derived key: " + extracted16); if(extracted16 == null) { System.out.println("Failed to derive 16 byte key with mechanism: CKM_EXTRACT_KEY_FROM_KEY \n"); } System.out.println("derivedKey 16 bytes: "); byte[] derivedBytes = extracted16.getEncoded(); displayByteArray(derivedBytes,true); /*****************************************************************************************************/ System.out.println("\n Mechanism CKM_EXTRACT_KEY_FROM_KEY test 8 bytes. \n"); SymmetricKeyDeriver extract8 = token.getSymmetricKeyDeriver(); extract8.initDerive( extracted16, PKCS11Constants.CKM_EXTRACT_KEY_FROM_KEY,param,null, PKCS11Constants.CKA_ENCRYPT, PKCS11Constants.CKA_DERIVE,(long) 8); SymmetricKey extracted8 = extract8.derive(); System.out.println("Derived key: " + extracted8); if(extracted8 == null) { System.out.println("Failed to derive key extracted 8 bytes with mechanism: CKM_EXTRACT_KEY_FROM_KEY \n"); } byte[] extracted8Bytes = extracted8.getEncoded(); System.out.println("derived extracted 8 bytes of key: "); displayByteArray(extracted8Bytes,true); /*****************************************************************************************************/ System.out.println("\n Mechanism CKM_CONCATENATE_BASE_AND_KEY test 16 + 8 = 24 byte key. \n"); SymmetricKeyDeriver concat = keyToken.getSymmetricKeyDeriver(); concat.initDerive( extracted16,extracted8, PKCS11Constants.CKM_CONCATENATE_BASE_AND_KEY,null,null, PKCS11Constants.CKM_DES3_ECB, PKCS11Constants.CKA_DERIVE,(long) 0); SymmetricKey concated24 = concat.derive(); if( concated24 == null) { System.out.println("Failed to derive key concated 8 bytes to 16 bytes key: CKM_CONCATENATE_BASE_AND_KEY \n"); } byte[] concated24Bytes = concated24.getEncoded(); System.out.println("derived concated 16 + 8 = 24 byte key: "); displayByteArray(concated24Bytes,true); /*****************************************************************************************************/ // Try ecnrypted des3 derivation System.out.println("\n Mechanism CKM_DES3_ECB_ENCRYPT_DATA test. \n"); SymmetricKeyDeriver encryptDes3 = token.getSymmetricKeyDeriver(); encryptDes3.initDerive( baseKey, /* PKCS11Constants.CKM_DES3_ECB_ENCRYPT_DATA */ 4354L ,derivationData16 ,null, PKCS11Constants.CKM_DES3_ECB, PKCS11Constants.CKA_DERIVE,(long) 16); SymmetricKey encrypted16 = encryptDes3.derive(); if ( encrypted16 == null) { System.out.println("Failed to derive 16 bytes from encrypted derivation data."); } byte[] encrypted16Bytes = encrypted16.getEncoded(); System.out.println("derived encrypted 16 bytes: " + encrypted16Bytes.length); displayByteArray(encrypted16Bytes,true); Cipher cipher = keyToken.getCipherContext(EncryptionAlgorithm.DES3_ECB); cipher.initEncrypt(baseKey); byte[] ciphertext = cipher.doFinal(derivationData16); displayByteArray(ciphertext,true); if ( ciphertext.length != encrypted16Bytes.length ) { System.out.println("FAILED: encrypted data length not equal to derived key length."); } else { for ( int i = 0; i < ciphertext.length ; i ++) { ciphertext[i]&=0xfe; encrypted16Bytes[i]&=0xfe; } if ( Arrays.equals(ciphertext, encrypted16Bytes)) { System.out.println("PASSED: derived key the same as encrypted data."); } else { System.out.println("FAILED: derived key not the same as encrypted data."); } } /*****************************************************************************************************/ System.out.println("\n Mechanism CKM_DES3_CBC_ENCRYPT_DATA test. \n"); SymmetricKeyDeriver encryptDes3CBC = token.getSymmetricKeyDeriver(); encryptDes3CBC.initDerive( baseKey, /* PKCS11Constants.CKM_DES3_CBC_ENCRYPT_DATA */ 4355L ,derivationData16 ,iv8, PKCS11Constants.CKM_DES3_CBC, PKCS11Constants.CKA_DERIVE,(long) 16); SymmetricKey encryptedDes3CBC = encryptDes3CBC.derive(); if ( encryptedDes3CBC == null) { System.out.println("Failed to derive 16 bytes from encrypted derivation data."); } byte[] encryptedDes3CBCBytes = encryptedDes3CBC.getEncoded(); System.out.println("derived encrypted 16 bytes: " + encryptedDes3CBCBytes.length); displayByteArray(encryptedDes3CBCBytes,true); cipher = keyToken.getCipherContext(EncryptionAlgorithm.DES3_CBC); cipher.initEncrypt(baseKey,new IVParameterSpec(iv8)); ciphertext = cipher.doFinal(derivationData16); displayByteArray(ciphertext,true); if ( ciphertext.length != encryptedDes3CBCBytes.length ) { System.out.println("FAILED: encrypted data length not equal to derived key length."); } else { for ( int i = 0; i < ciphertext.length ; i ++) { ciphertext[i]&=0xfe; encryptedDes3CBCBytes[i]&=0xfe; } if ( Arrays.equals(ciphertext, encryptedDes3CBCBytes)) { System.out.println("PASSED: derived key the same as encrypted data."); } else { System.out.println("FAILED: derived key not the same as encrypted data."); } } /*****************************************************************************************************/ System.out.println("\n Mechanism CKM_AES_ECB_ENCRYPT_DATA test. \n"); SymmetricKeyDeriver encryptAESECB = token.getSymmetricKeyDeriver(); //System.in.read(); encryptAESECB.initDerive( baseKeyAES, /* PKCS11Constants.CKM_AES_ECB_ENCRYPT_DATA */ 4356L ,derivationData16 ,null, PKCS11Constants.CKM_AES_ECB, PKCS11Constants.CKA_DERIVE,(long) 16); SymmetricKey encryptedAESECB = encryptAESECB.derive(); if ( encryptedAESECB == null) { System.out.println("Failed to derive 16 bytes from encrypted derivation data."); } byte[] encryptedAESECBBytes = encryptedAESECB.getEncoded(); System.out.println("derived encrypted 16 bytes: " + encryptedAESECBBytes.length); displayByteArray(encryptedAESECBBytes,true); cipher = keyToken.getCipherContext(EncryptionAlgorithm.AES_128_ECB); cipher.initEncrypt(baseKeyAES); ciphertext = cipher.doFinal(derivationData16); displayByteArray(ciphertext,true); if ( ciphertext.length != encryptedAESECBBytes.length ) { System.out.println("FAILED: encrypted data length not equal to derived key length."); } else { for ( int i = 0; i < ciphertext.length ; i ++) { ciphertext[i]&=0xfe; encryptedAESECBBytes[i]&=0xfe; } if ( Arrays.equals(ciphertext, encryptedAESECBBytes)) { System.out.println("PASSED: derived key the same as encrypted data."); } else { System.out.println("FAILED: derived key not the same as encrypted data."); } } /*****************************************************************************************************/ System.out.println("\n Mechanism CKM_AES_CBC_ENCRYPT_DATA test. \n"); SymmetricKeyDeriver encryptAESCBC= token.getSymmetricKeyDeriver(); //System.in.read(); encryptAESCBC.initDerive( baseKeyAES, /* PKCS11Constants.CKM_AES_CBC_ENCRYPT_DATA */ 4357L ,derivationData16 ,iv16, PKCS11Constants.CKM_AES_CBC, PKCS11Constants.CKA_DERIVE,(long) 16); SymmetricKey encryptedAESCBC = encryptAESCBC.derive(); if ( encryptedAESCBC == null) { System.out.println("Failed to derive 16 bytes from encrypted derivation data."); } byte[] encryptedAESCBCBytes = encryptedAESCBC.getEncoded(); System.out.println("derived encrypted 16 bytes: " + encryptedAESCBCBytes.length); displayByteArray(encryptedAESCBCBytes,true); cipher = keyToken.getCipherContext(EncryptionAlgorithm.AES_128_CBC); cipher.initEncrypt(baseKeyAES,new IVParameterSpec(iv16)); ciphertext = cipher.doFinal(derivationData16); displayByteArray(ciphertext,true); if ( ciphertext.length != encryptedAESCBCBytes.length ) { System.out.println("FAILED: encrypted data length not equal to derived key length."); } else { for ( int i = 0; i < ciphertext.length ; i ++) { ciphertext[i]&=0xfe; encryptedAESCBCBytes[i]&=0xfe; } if ( Arrays.equals(ciphertext, encryptedAESCBCBytes)) { System.out.println("PASSED: derived key the same as encrypted data."); } else { System.out.println("FAILED: derived key not the same as encrypted data."); } } // get vector of symkeys Enumeration ect = null; ect = (Enumeration) cm.getAllTokens(); CryptoToken ct = null; //ct = cm.getTokenByName("ePass Token"); while (ect.hasMoreElements()) { ct = ect.nextElement(); System.out.println("CryptoToken.name= " + ct.getName()); } SymmetricKey[] keys = keyToken.getCryptoStore().getSymmetricKeys(); SymmetricKey macKey = getSymKeyByName(keys, "defKeySet-macKey"); System.out.println("macKey: " + macKey); } public static void displayByteArray(byte[] ba, boolean has_check_sum) { char mask = 0xff; if ( has_check_sum == true ) mask = 0xfe; for(int i=0; i < ba.length; i++) { System.out.print( Integer.toHexString(ba[i]&mask) + " " ); if( (i % 26) == 25 ) { System.out.println(""); } } System.out.println(""); } public static byte[] longToBytes(long x) { ByteBuffer buffer = ByteBuffer.allocate(8); buffer.putLong(x); return buffer.array(); } public static byte[] concatByteArrays(byte[] a, byte[] b) { byte[] result = new byte[a.length + b.length]; System.arraycopy(a, 0, result, 0, a.length); System.arraycopy(b, 0, result, a.length, b.length); return result; } public static SymmetricKey getSymKeyByName( SymmetricKey[] keys, String name) { if ( keys == null || name == null ) { return null; } int len = keys.length; for(int i = 0 ; i < len ; i++ ) { SymmetricKey cur = keys[i]; if ( cur != null ) { if( name.equals(cur.getNickName())) { System.out.println("Found key: " + name + "\n"); return cur; } } } return null; } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/SymKeyGen.java000066400000000000000000000321601412550063600237230ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.security.InvalidAlgorithmParameterException; import java.security.spec.AlgorithmParameterSpec; import java.util.LinkedList; import java.util.List; import javax.crypto.spec.RC2ParameterSpec; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.NotInitializedException; import org.mozilla.jss.crypto.Cipher; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.EncryptionAlgorithm; import org.mozilla.jss.crypto.IVParameterSpec; import org.mozilla.jss.crypto.KeyGenAlgorithm; import org.mozilla.jss.crypto.KeyGenerator; import org.mozilla.jss.crypto.PBEAlgorithm; import org.mozilla.jss.crypto.PBEKeyGenParams; import org.mozilla.jss.crypto.SymmetricKey; import org.mozilla.jss.pkcs11.PK11SecureRandom; import org.mozilla.jss.util.Password; /** * Most of this code is Deprecated look at JCASymKeyGen.java for sample. */ public class SymKeyGen { private CryptoToken token = null; byte[] plainText16Bytes = "Firefox rules!".getBytes(); /* 16 bytes */ byte[] plainText18Bytes = "Thunderbird rules!".getBytes(); /* 18 bytes */ public SymmetricKey genPBEKey(PBEAlgorithm alg, SymmetricKey.Type keyType, int keyStrength) throws Exception { SymmetricKey key = null; byte[] keyData; KeyGenerator kg = token.getKeyGenerator(alg); try { //this is debug code you don't initialize //PBE algs with key Strength doing this should throw //InvaldAlgortithmParameterException kg.initialize(keyStrength); throw new Exception("ERROR: Initializing PBE key with strength " + keyStrength + " succeeded"); } catch( InvalidAlgorithmParameterException e) { } Password pass = new Password( ("passwd1").toCharArray() ); byte[] salt = genSalt(alg.getSaltLength()); PBEKeyGenParams kgp = new PBEKeyGenParams(pass, salt, 2); pass.clear(); kg.initialize(kgp); key = kg.generate(); kgp.clear(); if( key.getType() != keyType ) { throw new Exception("Wrong key type: "+key.getType()); } if( ! key.getOwningToken().equals( token ) ) { throw new Exception("wrong token"); } if( key.getStrength() != keyStrength ) { throw new Exception("wrong strength: "+key.getStrength()); } return key; } public SymmetricKey genPBAKey(KeyGenAlgorithm alg, SymmetricKey.Type keyType, int keyStrength) throws Exception { SymmetricKey key = null; byte[] keyData; KeyGenerator kg = token.getKeyGenerator(alg); try { //this is debug code you don't initialize //PBE algs with key Strength doing this should throw //InvalidAlgorithmParameterException kg.initialize(keyStrength); throw new Exception("ERROR: Initializing PBE key with strength "+ keyStrength + " succeeded"); } catch( InvalidAlgorithmParameterException e) { } Password pass = new Password( ("passwd1").toCharArray() ); byte[] salt = genSalt(8); PBEKeyGenParams kgp = new PBEKeyGenParams(pass, salt, 2); pass.clear(); kg.initialize(kgp); key = kg.generate(); kgp.clear(); if( key.getType() != keyType ) { throw new Exception("Wrong key type: "+key.getType()); } if( ! key.getOwningToken().equals( token ) ) { throw new Exception("wrong token"); } if( key.getStrength() != keyStrength ) { throw new Exception("wrong strength: "+key.getStrength()); } return key; } public SymmetricKey genSymKey(KeyGenAlgorithm alg, SymmetricKey.Type keyType , int keyStrength, int keyLength) throws Exception { SymmetricKey key = null; byte[] keyData; KeyGenerator kg = token.getKeyGenerator(alg); if (alg == KeyGenAlgorithm.AES || alg == KeyGenAlgorithm.RC4 || alg == KeyGenAlgorithm.RC2) { kg.initialize (keyStrength); } key = kg.generate(); if( key.getType() != keyType ) { throw new Exception("wrong algorithm"); } if( ! key.getOwningToken().equals( token ) ) { throw new Exception("wrong token"); } if( key.getStrength() != keyStrength ) { throw new Exception("wrong strength"); } keyData = key.getKeyData(); if( keyData.length != keyLength ) { throw new Exception("key data wrong length: " + keyData.length); } return key; } public boolean cipherTest(SymmetricKey key, EncryptionAlgorithm eAlg ) throws Exception { boolean bStatus = false; int ivLength = 0; AlgorithmParameterSpec algParSpec = null; Cipher cipher = null; cipher = token.getCipherContext(eAlg); // if no padding is used plainText needs to be fixed length // block divisable by 8 bytes byte[] plaintext = plainText18Bytes; if ((eAlg.getMode() == EncryptionAlgorithm.Mode.CBC || eAlg.getMode() == EncryptionAlgorithm.Mode.ECB ) && eAlg.getPadding() == EncryptionAlgorithm.Padding.NONE) { plaintext = plainText16Bytes; } // size 0 means this algorithm does not take an IV. // you need to use the same IV for Encrypt/Decrypt ivLength = eAlg.getIVLength(); if (ivLength != 0 ) { algParSpec = genIV(ivLength); } if (key.getType() == SymmetricKey.RC2) { byte[] iv = new byte[ivLength]; PK11SecureRandom rng = new PK11SecureRandom(); rng.nextBytes(iv); algParSpec = new RC2ParameterSpec(40, iv); } if (algParSpec == null) { cipher.initEncrypt(key); } else { cipher.initEncrypt(key, algParSpec); } byte[] ciphertext = cipher.doFinal(plaintext); if (ivLength == 0) { cipher.initDecrypt(key); } else { cipher.initDecrypt(key, algParSpec); } byte[] recovered = cipher.doFinal(ciphertext); if( recovered.length != plaintext.length ) { throw new Exception("Recovered plaintext has different length ("+ recovered.length+") than original ("+plaintext.length+")"); } if (java.util.Arrays.equals(plaintext, recovered) ) { bStatus = true; } else { throw new Exception("ERROR: unable to recover plaintext"); } return bStatus; // no exception was thrown. } private SymKeyGen( String certDbLoc) { try { CryptoManager cm = CryptoManager.getInstance(); token = cm.getInternalCryptoToken(); } catch (NotInitializedException ex) { ex.printStackTrace(); } } public IVParameterSpec genIV(int blockSize) throws Exception { // generate an IV byte[] iv = new byte[blockSize]; PK11SecureRandom rng = new PK11SecureRandom(); rng.nextBytes(iv); return new IVParameterSpec(iv); } public byte[] genSalt(int saltSize) throws Exception { byte[] salt = new byte[saltSize]; PK11SecureRandom rng = new PK11SecureRandom(); rng.nextBytes(salt); return salt; } class alg { public KeyGenAlgorithm sAlg; public SymmetricKey.Type keyType; public int size; public int blkSize; List ciphers = new LinkedList<>(); public alg (KeyGenAlgorithm alg, SymmetricKey.Type kType, int sz, int bSize) { sAlg = alg; keyType = kType; size = sz; blkSize = bSize; } public void setEncAlgs(List c) { ciphers = c; } } public static void main(String args[]) { try { if ( args.length < 1 ) { System.out.println("Usage: java org.mozilla.jss.tests." + "SymKeyGen "); System.exit(1); } SymKeyGen skg = new SymKeyGen(args[0]); SymmetricKey key = null; //DES Key key = skg.genSymKey(KeyGenAlgorithm.DES, SymmetricKey.DES, 56, 8); skg.cipherTest(key, EncryptionAlgorithm.DES_CBC_PAD); skg.cipherTest(key, EncryptionAlgorithm.DES_CBC); skg.cipherTest(key, EncryptionAlgorithm.DES_ECB); System.out.println("DES key and cipher tests correct"); // DES3 key key = skg.genSymKey(KeyGenAlgorithm.DES3, SymmetricKey.DES3, 168, 24); skg.cipherTest(key, EncryptionAlgorithm.DES3_CBC_PAD); skg.cipherTest(key, EncryptionAlgorithm.DES3_CBC); skg.cipherTest(key, EncryptionAlgorithm.DES3_ECB); System.out.println("DESede key and cipher tests correct"); // AES 128 key key = skg.genSymKey(KeyGenAlgorithm.AES, SymmetricKey.AES, 128, 128/8); skg.cipherTest(key, EncryptionAlgorithm.AES_128_CBC); skg.cipherTest(key, EncryptionAlgorithm.AES_128_ECB); skg.cipherTest(key, EncryptionAlgorithm.AES_128_CBC_PAD); System.out.println("AES 128 key and cipher tests correct"); // AES 192 key key = skg.genSymKey(KeyGenAlgorithm.AES, SymmetricKey.AES, 192, 192/8); skg.cipherTest(key, EncryptionAlgorithm.AES_192_CBC); skg.cipherTest(key, EncryptionAlgorithm.AES_192_ECB); skg.cipherTest(key, EncryptionAlgorithm.AES_192_CBC_PAD); System.out.println("AES 192 key and cipher tests correct"); // AES 256 key key = skg.genSymKey(KeyGenAlgorithm.AES, SymmetricKey.AES, 256, 256/8); skg.cipherTest(key, EncryptionAlgorithm.AES_256_CBC); skg.cipherTest(key, EncryptionAlgorithm.AES_256_ECB); skg.cipherTest(key, EncryptionAlgorithm.AES_256_CBC_PAD); System.out.println("AES 256 key and cipher tests correct"); // RC2 Key key = skg.genSymKey(KeyGenAlgorithm.RC2, SymmetricKey.RC2, 40, 5); skg.cipherTest(key, EncryptionAlgorithm.RC2_CBC); skg.cipherTest(key, EncryptionAlgorithm.RC2_CBC_PAD); System.out.println("RC2 key and cipher tests correct"); // RC4 key key = skg.genSymKey(KeyGenAlgorithm.RC4, SymmetricKey.RC4, 128, 128/8); skg.cipherTest(key, EncryptionAlgorithm.RC4); System.out.println("RC4 key and cipher tests correct"); //Todo //KeyGenAlgorithm.PBA_SHA1_HMAC, SymmetricKey.SHA1_HMAC, 160); //PBE key gen test. // PBEAlgorithm.PBE_MD2_DES_CBC key = skg.genPBEKey(PBEAlgorithm.PBE_MD2_DES_CBC, SymmetricKey.DES, 56); skg.cipherTest(key, EncryptionAlgorithm.DES_CBC_PAD); skg.cipherTest(key, EncryptionAlgorithm.DES_CBC); skg.cipherTest(key, EncryptionAlgorithm.DES_ECB); //PBEAlgorithm.PBE_MD5_DES_CBC key = skg.genPBEKey(PBEAlgorithm.PBE_MD5_DES_CBC, SymmetricKey.DES, 56); skg.cipherTest(key, EncryptionAlgorithm.DES_CBC_PAD); skg.cipherTest(key, EncryptionAlgorithm.DES_CBC); skg.cipherTest(key, EncryptionAlgorithm.DES_ECB); //PBEAlgorithm.PBE_SHA1_DES_CBC key = skg.genPBEKey(PBEAlgorithm.PBE_SHA1_DES_CBC, SymmetricKey.DES, 64); skg.cipherTest(key, EncryptionAlgorithm.DES_CBC_PAD); skg.cipherTest(key, EncryptionAlgorithm.DES_CBC); skg.cipherTest(key, EncryptionAlgorithm.DES_ECB); //PBEAlgorithm.PBE_SHA1_DES3_CBC key = skg.genPBEKey(PBEAlgorithm.PBE_SHA1_DES3_CBC, SymmetricKey.DES3, 168); skg.cipherTest(key, EncryptionAlgorithm.DES3_CBC_PAD); skg.cipherTest(key, EncryptionAlgorithm.DES3_CBC); skg.cipherTest(key, EncryptionAlgorithm.DES3_ECB); //PBEAlgorithm.PBE_SHA1_RC2_40_CBC key = skg.genPBEKey(PBEAlgorithm.PBE_SHA1_RC2_40_CBC, SymmetricKey.RC2, 40); skg.cipherTest(key, EncryptionAlgorithm.RC2_CBC); skg.cipherTest(key, EncryptionAlgorithm.RC2_CBC_PAD); //PBEAlgorithm.PBE_SHA1_RC2_128_CBC key = skg.genPBEKey(PBEAlgorithm.PBE_SHA1_RC2_128_CBC, SymmetricKey.RC2, 128); skg.cipherTest(key, EncryptionAlgorithm.RC2_CBC); skg.cipherTest(key, EncryptionAlgorithm.RC2_CBC_PAD); //PBEAlgorithm.PBE_SHA1_RC4_40 key = skg.genPBEKey(PBEAlgorithm.PBE_SHA1_RC4_40, SymmetricKey.RC4, 40); skg.cipherTest(key, EncryptionAlgorithm.RC4); //PBEAlgorithm.PBE_SHA1_RC4_128 key = skg.genPBEKey(PBEAlgorithm.PBE_SHA1_RC4_128, SymmetricKey.RC4, 128); skg.cipherTest(key, EncryptionAlgorithm.RC4); System.out.println("Password Based key generation tests correct"); } catch(Exception e) { e.printStackTrace(); } } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/TeletexStringTest.java000066400000000000000000000210121412550063600255030ustar00rootroot00000000000000package org.mozilla.jss.tests; import java.io.IOException; import org.junit.Assert; import org.junit.Test; import org.mozilla.jss.netscape.security.util.DerValue; public class TeletexStringTest { public byte tag = DerValue.tag_T61String; @Test public void testEncodingEmptyString() throws Exception { String string = ""; System.out.println("Encoding: [" + string + "]"); byte[] expected = JSSUtil.encode(tag, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testDecodingEmptyString() throws Exception { String input = ""; byte[] data = JSSUtil.encode(tag, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: [" + input + "]"); String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + output + "]"); Assert.assertEquals(input, output); } @Test public void testEncodingNullCharacters() throws Exception { String string = StringTestUtil.NULL_CHARS; System.out.println("Encoding: [" + StringTestUtil.toString(string.getBytes()) + "]"); byte[] expected = JSSUtil.encode(tag, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); actual = StringTestUtil.normalizeUnicode(actual); System.out.println(" - norm. : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testDecodingNullCharacters() throws Exception { String input = StringTestUtil.NULL_CHARS; byte[] data = JSSUtil.encode(tag, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: [" + StringTestUtil.toString(input.getBytes()) + "]"); String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + StringTestUtil.toString(output.getBytes()) + "]"); Assert.assertEquals(input, output); } @Test public void testEncodingPrintableCharacters() throws Exception { String string = StringTestUtil.PRINTABLE_CHARS; System.out.println("Encoding: [" + string + "]"); byte[] expected = JSSUtil.encode(tag, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testDecodingPrintableCharacters() throws Exception { String input = StringTestUtil.PRINTABLE_CHARS; byte[] data = JSSUtil.encode(tag, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: [" + input + "]"); String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + output + "]"); Assert.assertEquals(input, output); } @Test public void testEncodingNonPrintableCharacters() throws Exception { String string = StringTestUtil.NON_PRINTABLE_CHARS; System.out.println("Encoding: [" + string + "]"); byte[] expected = JSSUtil.encode(tag, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testDecodingNonPrintableCharacters() throws Exception { String input = StringTestUtil.NON_PRINTABLE_CHARS; byte[] data = JSSUtil.encode(tag, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: [" + input + "]"); String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + output + "]"); Assert.assertEquals(input, output); } @Test public void testEncodingControlCharacters() throws Exception { String string = StringTestUtil.CONTROL_CHARS; System.out.println("Encoding: [" + StringTestUtil.toString(string.getBytes()) + "]"); byte[] expected = JSSUtil.encode(tag, string); System.out.println(" - expected: " + StringTestUtil.toString(expected)); byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.assertArrayEquals(expected, actual); } @Test public void testDecodingControlCharacters() throws Exception { String input = StringTestUtil.CONTROL_CHARS; byte[] data = JSSUtil.encode(tag, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: [" + StringTestUtil.toString(input.getBytes()) + "]"); String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + StringTestUtil.toString(output.getBytes()) + "]"); Assert.assertEquals(input, output); } @Test public void testEncodingMultibyteCharacters() throws Exception { String string = StringTestUtil.MULTIBYTE_CHARS; System.out.println("Encoding: [" + string + "]"); System.out.println(" - expected: IOException"); try { byte[] actual = StringTestUtil.encode(tag, string); System.out.println(" - actual : " + StringTestUtil.toString(actual)); Assert.fail(); } catch (Exception e) { System.out.println(" - actual : " + e.getClass().getSimpleName()); Assert.assertTrue(e instanceof IOException); } } @Test public void testDecodingMultibyteCharacters() throws Exception { String input = StringTestUtil.MULTIBYTE_CHARS; byte[] data = JSSUtil.encode(DerValue.tag_UTF8String, input); System.out.println("Decoding: [" + StringTestUtil.toString(data) + "]"); System.out.println(" - expected: IOException"); try { String output = StringTestUtil.decode(tag, data); System.out.println(" - actual : [" + StringTestUtil.toString(output.getBytes()) + "]"); Assert.fail(); } catch (Exception e) { System.out.println(" - actual : " + e.getClass().getSimpleName()); Assert.assertTrue(e instanceof IOException); } } @Test public void testEncodingTime() throws Exception { System.out.println("Encoding time:"); String string = StringTestUtil.NULL_CHARS + StringTestUtil.PRINTABLE_CHARS + StringTestUtil.NON_PRINTABLE_CHARS + StringTestUtil.CONTROL_CHARS; long t0 = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) JSSUtil.encode(tag, string); long t1 = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) StringTestUtil.encode(tag, string); long t2 = System.currentTimeMillis(); long time1 = t1 - t0; long time2 = t2 - t1; System.out.println(" - JSS : " + time1 + " ms"); System.out.println(" - Internal: " + time2 + " ms"); } @Test public void testDecodingTime() throws Exception { System.out.println("Decoding time:"); String string = StringTestUtil.NULL_CHARS + StringTestUtil.PRINTABLE_CHARS + StringTestUtil.NON_PRINTABLE_CHARS + StringTestUtil.CONTROL_CHARS; byte[] data = JSSUtil.encode(tag, string); long t0 = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) JSSUtil.decode(tag, data); long t1 = System.currentTimeMillis(); for (int i = 0; i < 10000; i++) StringTestUtil.decode(tag, data); long t2 = System.currentTimeMillis(); long time1 = t1 - t0; long time2 = t2 - t1; System.out.println(" - JSS : " + time1 + " ms"); System.out.println(" - Internal: " + time2 + " ms"); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/TestBuffer.java000066400000000000000000000050751412550063600241260ustar00rootroot00000000000000package org.mozilla.jss.tests; import org.mozilla.jss.nss.Buffer; import org.mozilla.jss.nss.BufferProxy; public class TestBuffer { public static void TestCreateFree() { BufferProxy buf = Buffer.Create(100); assert(buf != null); Buffer.Free(buf); } public static void TestReadWrite() { BufferProxy buf = Buffer.Create(10); byte[] data = { 0x01, 0x00, 0x02, 0x03 }; assert(buf != null); assert(Buffer.Write(buf, data) == 4); byte[] out_data = Buffer.Read(buf, 4); assert(out_data.length == 4); assert(out_data[0] == data[0]); assert(out_data[1] == data[1]); assert(out_data[2] == data[2]); assert(out_data[3] == data[3]); Buffer.Free(buf); } public static void TestCapacities() { BufferProxy buf = Buffer.Create(6); byte[] data = {0x00, 0x01, 0x02}; assert(buf != null); assert(Buffer.Capacity(buf) == 6); assert(Buffer.ReadCapacity(buf) == 0); assert(Buffer.WriteCapacity(buf) == 6); assert(!Buffer.CanRead(buf)); assert(Buffer.CanWrite(buf)); assert(Buffer.Write(buf, data) == data.length); assert(Buffer.CanRead(buf)); assert(Buffer.CanWrite(buf)); assert(Buffer.ReadCapacity(buf) == 3); assert(Buffer.WriteCapacity(buf) == 3); assert(Buffer.Write(buf, data) == data.length); assert(Buffer.CanRead(buf)); assert(!Buffer.CanWrite(buf)); assert(Buffer.ReadCapacity(buf) == 6); assert(Buffer.WriteCapacity(buf) == 0); Buffer.Free(buf); } public static void TestPutGet() { BufferProxy buf = Buffer.Create(2); assert(buf != null); assert(Buffer.Put(buf, (byte) 0x00) == 0x00); assert(Buffer.Get(buf) == 0x00); assert(Buffer.Get(buf) == -1); assert(Buffer.Put(buf, (byte) 0x01) == 0x01); assert(Buffer.Put(buf, (byte) 0x02) == 0x02); assert(Buffer.Put(buf, (byte) 0x03) == -1); assert(Buffer.Get(buf) == 0x01); assert(Buffer.Get(buf) == 0x02); assert(Buffer.Get(buf) == -1); Buffer.Free(buf); } public static void main(String[] args) { System.loadLibrary("jss"); System.out.println("Calling TestCreateFree()..."); TestCreateFree(); System.out.println("Calling TestReadWrite()..."); TestReadWrite(); System.out.println("Calling TestCapacities()..."); TestCapacities(); System.out.println("Calling TestPutGet()..."); TestPutGet(); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/TestBufferPRFD.c000066400000000000000000000053131412550063600240760ustar00rootroot00000000000000/* * Test case for Buffer PRFileDesc implementation located under the * org.mozilla.jss.ssl.javax package. This ensures that we can do a * basic SSL handshake and verify that it works alright. */ /* Optional, for enabling asserts */ #define DEBUG 1 /* Header file under test */ #include "BufferPRFD.h" /* NSPR required includes */ #include #include #include #include /* NSS includes */ #include #include #include #include #include #include #include #include /* Standard includes */ #include #include #include #include #include #include #include void test_getsocketoption(PRFileDesc *fd, size_t read_buf_len, size_t write_buf_len) { PRSocketOptionData opt; memset(&opt, 0, sizeof(opt)); opt.option = PR_SockOpt_Nonblocking; assert(PR_GetSocketOption(fd, &opt) == PR_SUCCESS); assert(opt.value.non_blocking == PR_TRUE); memset(&opt, 0, sizeof(opt)); opt.option = PR_SockOpt_Reuseaddr; assert(PR_GetSocketOption(fd, &opt) == PR_SUCCESS); assert(opt.value.reuse_addr == PR_TRUE); memset(&opt, 0, sizeof(opt)); opt.option = PR_SockOpt_Keepalive; assert(PR_GetSocketOption(fd, &opt) == PR_SUCCESS); assert(opt.value.keep_alive == PR_FALSE); memset(&opt, 0, sizeof(opt)); opt.option = PR_SockOpt_NoDelay; assert(PR_GetSocketOption(fd, &opt) == PR_SUCCESS); assert(opt.value.no_delay == PR_TRUE); memset(&opt, 0, sizeof(opt)); opt.option = PR_SockOpt_RecvBufferSize; assert(PR_GetSocketOption(fd, &opt) == PR_SUCCESS); assert(opt.value.recv_buffer_size == read_buf_len); memset(&opt, 0, sizeof(opt)); opt.option = PR_SockOpt_SendBufferSize; assert(PR_GetSocketOption(fd, &opt) == PR_SUCCESS); assert(opt.value.send_buffer_size == write_buf_len); } void test_read_write(PRFileDesc *fd) { } void test_with_buffer_size(size_t read_buf_len, size_t write_buf_len) { /* Initialize Read/Write Buffers */ j_buffer *read_buf = jb_alloc(read_buf_len); j_buffer *write_buf = jb_alloc(write_buf_len); PRFileDesc *fd = newBufferPRFileDesc(read_buf, write_buf, (uint8_t *) "localhost", 9); test_getsocketoption(fd, read_buf_len, write_buf_len); PR_Close(fd); jb_free(read_buf); jb_free(write_buf); } int main(int argc, char** argv) { if (argc != 1) { fprintf(stderr, "usage: %s\n", argv[0]); return 1; } test_with_buffer_size(1023, 1023); test_with_buffer_size(2048, 1023); test_with_buffer_size(1023, 2048); return 0; } jss-5.0.0/src/test/java/org/mozilla/jss/tests/TestBufferPRFD.java000066400000000000000000000260301412550063600245740ustar00rootroot00000000000000package org.mozilla.jss.tests; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.nss.Buffer; import org.mozilla.jss.nss.BufferProxy; import org.mozilla.jss.nss.PR; import org.mozilla.jss.nss.PRErrors; import org.mozilla.jss.nss.PRFDProxy; import org.mozilla.jss.nss.SSL; import org.mozilla.jss.nss.SSLFDProxy; import org.mozilla.jss.nss.SecurityStatusResult; import org.mozilla.jss.pkcs11.PK11Cert; import org.mozilla.jss.pkcs11.PK11PrivKey; import org.mozilla.jss.ssl.SSLAlertEvent; import org.mozilla.jss.ssl.SSLVersion; import org.mozilla.jss.ssl.SSLVersionRange; import org.mozilla.jss.util.Password; public class TestBufferPRFD { public static void TestCreateClose() { byte[] info = {0x01, 0x02, 0x03, 0x04}; BufferProxy left_read = Buffer.Create(10); BufferProxy right_read = Buffer.Create(10); assert(left_read != null); assert(right_read != null); PRFDProxy left = PR.NewBufferPRFD(left_read, right_read, info); PRFDProxy right = PR.NewBufferPRFD(right_read, left_read, info); assert(left != null); assert(right != null); assert(PR.Write(left, info) == 4); assert(PR.Send(left, info, 0, 0) == 4); assert(PR.Send(left, info, 0, 0) == 2); byte[] result = PR.Recv(right, 10, 0, 0); assert(result.length == 10); for (int i = 0; i < 10; i++) { assert(result[i] == info[i % info.length]); } assert(PR.Close(left) == PR.SUCCESS); assert(PR.Close(right) == PR.SUCCESS); Buffer.Free(left_read); Buffer.Free(right_read); } public static SSLFDProxy Setup_NSS_Client(PRFDProxy fd, String host) throws Exception { SSLFDProxy result = SSL.ImportFD(null, fd); assert(result != null); assert(SSL.ResetHandshake(result, false) == SSL.SECSuccess); assert(SSL.SetURL(result, host) == SSL.SECSuccess); TestSSLVersionGetSet(result); return result; } public static SSLFDProxy Setup_NSS_Server(PRFDProxy fd, String host, PK11Cert cert, PK11PrivKey key) throws Exception { SSLFDProxy result = SSL.ImportFD(null, fd); assert(result != null); assert(SSL.ConfigServerCert(result, cert, key) == SSL.SECSuccess); assert(SSL.ConfigServerSessionIDCache(1, 100, 100, null) == SSL.SECSuccess); assert(SSL.ResetHandshake(result, true) == SSL.SECSuccess); assert(SSL.SetURL(result, host) == SSL.SECSuccess); TestSSLVersionGetSet(result); return result; } public static boolean IsHandshakeFinished(SSLFDProxy c_nspr, SSLFDProxy s_nspr) { SecurityStatusResult c_result = SSL.SecurityStatus(c_nspr); SecurityStatusResult s_result = SSL.SecurityStatus(s_nspr); assert(c_result != null && s_result != null); return c_result.on == 1 && s_result.on == 1; } public static void TestSSLVersionGetSet(SSLFDProxy s_nspr) throws Exception { SSLVersionRange initial = SSL.VersionRangeGet(s_nspr); System.out.println("Initial: (" + initial.getMinVersion() + ":" + initial.getMinEnum() + ", " + initial.getMaxVersion() + ":" + initial.getMaxEnum() + ")"); SSLVersionRange vrange = new SSLVersionRange(SSLVersion.TLS_1_1, SSLVersion.TLS_1_3); assert(SSL.VersionRangeSet(s_nspr, vrange) == SSL.SECSuccess); SSLVersionRange actual = SSL.VersionRangeGet(s_nspr); System.out.println("Actual: (" + actual.getMinVersion() + ":" + actual.getMinEnum() + ", " + actual.getMaxVersion() + ":" + actual.getMaxEnum() + ")"); assert(actual.getMinEnum() <= SSLVersion.TLS_1_2.value()); assert(SSLVersion.TLS_1_2.value() <= actual.getMaxEnum()); } public static void InitializeCM(String database, String password) throws Exception { CryptoManager manager; manager = CryptoManager.getInstance(); manager.setPasswordCallback(new Password(password.toCharArray())); } public static void TestSSLHandshake(String server_nickname, String client_nickname) throws Exception { /* Constants */ String host = "localhost"; byte[] peer_info = host.getBytes(); /* Find SSL Server Certificate */ CryptoManager manager = CryptoManager.getInstance(); PK11Cert server_cert = (PK11Cert) manager.findCertByNickname(server_nickname); PK11PrivKey server_key = (PK11PrivKey) manager.findPrivKeyByCert(server_cert); assert(server_cert != null); assert(server_cert instanceof PK11Cert); assert(server_key != null); assert(server_key instanceof PK11PrivKey); /* Find SSL Client Certificate, if nickname given. */ PK11Cert client_cert = null; if (client_nickname != null) { client_cert = (PK11Cert) manager.findCertByNickname(client_nickname); assert(client_cert != null); } /* Create Buffers and BufferPRFDs */ BufferProxy read_buf = Buffer.Create(1024); BufferProxy write_buf = Buffer.Create(1024); assert(read_buf != null); assert(write_buf != null); PRFDProxy c_buffer = PR.NewBufferPRFD(read_buf, write_buf, peer_info); PRFDProxy s_buffer = PR.NewBufferPRFD(write_buf, read_buf, peer_info); assert(c_buffer != null); assert(s_buffer != null); SSLFDProxy c_nspr = Setup_NSS_Client(c_buffer, host); SSLFDProxy s_nspr = Setup_NSS_Server(s_buffer, host, server_cert, server_key); assert(c_nspr != null); assert(s_nspr != null); /* Apply Client Certificate, if given. When given, request it as the * server. */ if (client_cert != null) { c_nspr.SetClientCert(client_cert); assert(SSL.AttachClientCertCallback(c_nspr) == SSL.SECSuccess); assert(SSL.OptionSet(s_nspr, SSL.REQUEST_CERTIFICATE, 1) == SSL.SECSuccess); } /* Attach alert logging callback handler. */ assert(SSL.EnableAlertLogging(c_nspr) == SSL.SECSuccess); assert(SSL.EnableAlertLogging(s_nspr) == SSL.SECSuccess); assert(!IsHandshakeFinished(c_nspr, s_nspr)); /* Try a handshake */ int count = 0; while(!IsHandshakeFinished(c_nspr, s_nspr)) { if (SSL.ForceHandshake(c_nspr) != SSL.SECSuccess) { int error = PR.GetError(); if (error != PRErrors.WOULD_BLOCK_ERROR) { System.out.println("Unexpected error: " + new String(PR.ErrorToName(error)) + " (" + error + ")"); System.exit(1); } } if (SSL.ForceHandshake(s_nspr) != SSL.SECSuccess) { int error = PR.GetError(); if (error != PRErrors.WOULD_BLOCK_ERROR) { System.out.println("Unexpected error: " + new String(PR.ErrorToName(error)) + " (" + error + ")"); System.exit(1); } } count += 1; if (count >= 40) { System.err.println("Error: unable to make progress after " + count + " steps!"); System.exit(1); } } System.out.println("Handshake completed successfully!\n"); assert(IsHandshakeFinished(c_nspr, s_nspr)); /* Test peer data */ assert(SSL.PeerCertificate(c_nspr) != null); assert(SSL.PeerCertificateChain(c_nspr) != null); if (client_nickname == null) { assert(SSL.PeerCertificate(s_nspr) == null); assert(SSL.PeerCertificateChain(s_nspr) == null); } else { assert(SSL.PeerCertificate(s_nspr) != null); assert(SSL.PeerCertificateChain(s_nspr) != null); } /* Send data from client -> server */ byte[] client_message = "Cooking MCs".getBytes(); assert(PR.Write(c_nspr, client_message) == client_message.length); byte[] server_received = PR.Read(s_nspr, client_message.length); assert(server_received != null); if (server_received.length != client_message.length) { System.out.println("Expected a client message of length " + client_message.length + " but got one of " + server_received.length); System.exit(1); } for (int i = 0; i < client_message.length && i < server_received.length; i++) { if (client_message[i] != server_received[i]) { System.out.println("Received byte " + server_received[i] + " on server but expected " + client_message[i]); System.exit(1); } } /* Send data from server -> client */ byte[] server_message = "like a pound of bacon".getBytes(); assert(PR.Write(s_nspr, server_message) == server_message.length); byte[] client_received = PR.Read(c_nspr, server_message.length); assert(client_received != null); if (client_received.length != server_message.length) { System.out.println("Expected a server message of length " + server_message.length + " but got one of " + client_received.length); System.exit(1); } for (int i = 0; i < server_message.length && i < client_received.length; i++) { if (server_message[i] != client_received[i]) { System.out.println("Received byte " + client_received[i] + " on client but expected " + server_message[i]); System.exit(1); } } /* Close connections */ assert(PR.Shutdown(c_nspr, PR.SHUTDOWN_BOTH) == PR.SUCCESS); assert(PR.Shutdown(s_nspr, PR.SHUTDOWN_BOTH) == PR.SUCCESS); /* Print all alerts. */ for (SSLAlertEvent alert : c_nspr.inboundAlerts) { System.err.println("client inbound: " + alert); } for (SSLAlertEvent alert : c_nspr.outboundAlerts) { System.err.println("client outbound: " + alert); } for (SSLAlertEvent alert : s_nspr.inboundAlerts) { System.err.println("server inbound: " + alert); } for (SSLAlertEvent alert : s_nspr.outboundAlerts) { System.err.println("server outbound: " + alert); } /* Clean up */ assert(PR.Close(c_nspr) == PR.SUCCESS); assert(PR.Close(s_nspr) == PR.SUCCESS); Buffer.Free(read_buf); Buffer.Free(write_buf); } public static void main(String[] args) throws Exception { System.loadLibrary("jss"); System.out.println("Calling TestCreateClose()..."); TestCreateClose(); System.out.println("Initializing CryptoManager..."); InitializeCM(args[0], args[1]); System.out.println("Calling TestSSLHandshake(Server_RSA, null)..."); TestSSLHandshake("Server_RSA", null); System.out.println("Calling TestSSLHandshake(Server_RSA, Client_RSA)..."); TestSSLHandshake("Server_RSA", "Client_RSA"); System.out.println("Calling TestSSLHandshake(Server_ECDSA, null)..."); TestSSLHandshake("Server_ECDSA", null); System.out.println("Calling TestSSLHandshake(Server_ECDSA, Client_ECDSA)..."); TestSSLHandshake("Server_ECDSA", "Client_ECDSA"); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/TestBufferPRFDSSL.c000066400000000000000000000345131412550063600244640ustar00rootroot00000000000000/* * Test case for Buffer PRFileDesc implementation located under the * org.mozilla.jss.ssl.javax package. This ensures that we can do a * basic SSL handshake and verify that it works alright. */ /* Optional, for enabling asserts */ #define DEBUG 1 /* Header file under test */ #include "BufferPRFD.h" /* NSPR required includes */ #include #include #include #include /* NSS includes */ #include #include #include #include #include #include #include #include #include /* Standard includes */ #include #include #include #include #include #include static char *return_password(PK11SlotInfo *slot, PRBool retry, void *arg) { /* Return the password passed in via arg as the password for the PKCS11 * slot. From NSS semantics it appears that this function should allocate * a new copy with strdup as the caller expects to free it. */ if (retry == PR_FALSE) { return strdup((char*) arg); } else { /* Since arg is static, exit on an incorrect password; otherwise, * we'd be stuck in an infinite loop as there's no way to change * the value of arg. */ fprintf(stderr, "Error: Incorrect password!\n"); exit(1); } } static void setup_nss_context(char *database) { /* Create NSS Context to reference the given NSS DB and initialize the * NSS context with the database connection. */ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); NSSInitContext *const ctx = NSS_InitContext(database, "", "", "", NULL, NSS_INIT_READONLY | NSS_INIT_PK11RELOAD); if (ctx == NULL) { const PRErrorCode err = PR_GetError(); fprintf(stderr, "error: NSPR error code %d: %s\n", err, PR_ErrorToName(err)); exit(1); } if (NSS_Init(database) != SECSuccess) { const PRErrorCode err = PR_GetError(); fprintf(stderr, "error: NSPR error code when doing NSS_Init %d: %s\n", err, PR_ErrorToName(err)); exit(1); } } static PRFileDesc *setup_nss_client(PRFileDesc *c_nspr, char *host) { /* Configure the client end of the TLS connection. */ /* Note that most of this comes from the Fedora guide link: */ // https://docs.fedoraproject.org/en-US/Fedora_Security_Team/1/html/Defensive_Coding/sect-Defensive_Coding-TLS-Client-NSS.html PRFileDesc *model = PR_NewTCPSocket(); PRFileDesc *newfd = SSL_ImportFD(NULL, model); if (newfd == NULL) { const PRErrorCode err = PR_GetError(); fprintf(stderr, "error: NSPR error code %d: %s\n", err, PR_ErrorToName(err)); exit(1); } model = newfd; newfd = SSL_ImportFD(model, c_nspr); if (newfd == NULL) { const PRErrorCode err = PR_GetError(); fprintf(stderr, "error: SSL_ImportFD error %d: %s\n", err, PR_ErrorToName(err)); exit(1); } c_nspr = newfd; PR_Close(model); // Reset the handshake status after importing. if (SSL_ResetHandshake(c_nspr, PR_FALSE) != SECSuccess) { const PRErrorCode err = PR_GetError(); fprintf(stderr, "error: SSL_ResetHandshake error %d: %s\n", err, PR_ErrorToName(err)); exit(1); } if (SSL_SetURL(c_nspr, host) != SECSuccess) { const PRErrorCode err = PR_GetError(); fprintf(stderr, "error: SSL_SetURL error %d: %s\n", err, PR_ErrorToName(err)); exit(1); } return c_nspr; } static CERTCertificate *get_cert(char *host) { /* Find and return the certificate for the given host in the NSS DB; * this is only the public key. */ /* Code adapted from mod_nss. */ CERTCertList *clist; CERTCertListNode *cln; /* To do this, we have to iterate over all certs in the "user" NSS * database and see if any has a nickname matching the hostname. */ clist = PK11_ListCerts(PK11CertListUser, NULL); for (cln = CERT_LIST_HEAD(clist); !CERT_LIST_END(cln, clist); cln = CERT_LIST_NEXT(cln)) { CERTCertificate *cert = cln->cert; const char *nickname = (const char*)cln->appData; if (!nickname) { nickname = cert->nickname; } if (strcmp(host, nickname) == 0) { printf("Found cert with nickname: %s\n", nickname); return cert; } } CERT_DestroyCertList(clist); return NULL; } static SECKEYPrivateKey *get_privkey(CERTCertificate *cert, char *password) { /* For the given certificate, return the matching private key. Uses * password as authentication to the PKCS11 database if necessary. */ /* Code adapted from mod_nss. */ PK11SlotInfo *slot = NULL; /* First get the "default" slot -- this is the slot that GenerateTestCert * places its certificates in. */ slot = PK11_GetInternalKeySlot(); if (slot == NULL) { printf("Error finding internal slot!\n"); exit(2); } /* Since the JSS test suite uses a password on its database, we need a * shim function that returns the string. Note that this is implemented * in various places in NSS, but not exposed to calling applications. */ PK11_SetPasswordFunc(return_password); PRInt32 rv = PK11_Authenticate(slot, PR_TRUE, password); if (rv != SECSuccess) { /* This branch won't be reached as our return_password calls exit for * us on an incorrect password. */ printf("Invalid password for slot!\n"); const PRErrorCode err = PR_GetError(); fprintf(stderr, "error %d: %s\n", err, PR_ErrorToName(err)); exit(3); } return PK11_FindPrivateKeyFromCert(slot, cert, NULL); } static PRFileDesc *setup_nss_server(PRFileDesc *s_nspr, char *host, char *password, char *nickname, SECKEYPrivateKey **priv_key) { /* Set up the server end of the SSL connection and find certificates. */ /* Adapted from aforementioned Fedora developer guide and mod_nss. */ CERTCertificate *cert = get_cert(nickname); if (cert == NULL) { printf("Failed to find certificate for host: %s\n", host); exit(1); } *priv_key = get_privkey(cert, password); if (*priv_key == NULL) { printf("Failed to find private key for certificate for host: %s\n", host); const PRErrorCode err = PR_GetError(); fprintf(stderr, "error %d: %s\n", err, PR_ErrorToName(err)); exit(1); } PRFileDesc *model = PR_NewTCPSocket(); PRFileDesc *newfd = SSL_ImportFD(NULL, model); if (newfd == NULL) { const PRErrorCode err = PR_GetError(); fprintf(stderr, "error: NSPR error code %d: %s\n", err, PR_ErrorToName(err)); exit(1); } model = newfd; newfd = SSL_ImportFD(model, s_nspr); if (newfd == NULL) { const PRErrorCode err = PR_GetError(); fprintf(stderr, "error: SSL_ImportFD error %d: %s\n", err, PR_ErrorToName(err)); exit(1); } s_nspr = newfd; PR_Close(model); /* This part differs from the client side: set the certificate and * private key we're using. */ if (SSL_ConfigServerCert(s_nspr, cert, *priv_key, NULL, 0) != SECSuccess) { const PRErrorCode err = PR_GetError(); fprintf(stderr, "error: SSL_ConfigServerCert error %d: %s\n", err, PR_ErrorToName(err)); exit(1); } /* We need to initialize the SessionID cache, else NSS will segfault * because it has zero size when it tries to insert the new * connection into the cache... */ SSL_ConfigServerSessionIDCache(1, 100, 100, NULL); // Reset the handshake status -- server end if (SSL_ResetHandshake(s_nspr, PR_TRUE) != SECSuccess) { const PRErrorCode err = PR_GetError(); fprintf(stderr, "error: SSL_ResetHandshake error %d: %s\n", err, PR_ErrorToName(err)); exit(1); } if (SSL_SetURL(s_nspr, host) != SECSuccess) { const PRErrorCode err = PR_GetError(); fprintf(stderr, "error: SSL_SetURL error %d: %s\n", err, PR_ErrorToName(err)); exit(1); } return s_nspr; } bool is_finished(PRFileDesc *c_nspr, PRFileDesc *s_nspr) { /* Check whether or not the SSL Handshake has finished on both sides of * the connection. Since we cannot be guaranteed that the handshake was * successful, check whether SSL isn't off, i.e., is on or failed. */ int c_sec_status; int s_sec_status; if (SSL_SecurityStatus(c_nspr, &c_sec_status, NULL, NULL, NULL, NULL, NULL) != SECSuccess) { const PRErrorCode err = PR_GetError(); fprintf(stderr, "error: SSL_SecurityStatus error %d: %s\n", err, PR_ErrorToName(err)); exit(1); } if (SSL_SecurityStatus(s_nspr, &s_sec_status, NULL, NULL, NULL, NULL, NULL) != SECSuccess) { const PRErrorCode err = PR_GetError(); fprintf(stderr, "error: SSL_SecurityStatus error %d: %s\n", err, PR_ErrorToName(err)); exit(1); } return c_sec_status != SSL_SECURITY_STATUS_OFF && s_sec_status != SSL_SECURITY_STATUS_OFF; } int main(int argc, char** argv) { if (argc != 4) { fprintf(stderr, "usage: %s /path/to/nssdb password cert-nickname\n", argv[0]); exit(1); } setup_nss_context(argv[1]); /* Initialize Read/Write Buffers */ /* In order to maintain complete control over our buffers, we need to * create our buffers, sizes, and pointers here. This means that the * PRFileDesc does nothing except hold pointers to our memory and update * the contents/values as it sees fit (send/recv). If instead the buffer * took access (or created access itself), we'd need to get access to * them befor giving it to NSS, as NSS wraps our PRFileDesc in one of * their PRFileDescs, removing our access to fd->secret. */ j_buffer *c_read_buf = jb_alloc(4096); j_buffer *c_write_buf = jb_alloc(4096); PRFileDesc *c_nspr = newBufferPRFileDesc(c_read_buf, c_write_buf, (uint8_t*) "localhost", 9); /* Initialize Server Buffers */ PRFileDesc *s_nspr = newBufferPRFileDesc(c_write_buf, c_read_buf, (uint8_t*) "localhost", 9); /* Set up client and server sockets with NSSL */ char *host = "localhost"; SECKEYPrivateKey *priv_key; c_nspr = setup_nss_client(c_nspr, host); s_nspr = setup_nss_server(s_nspr, host, argv[2], argv[3], &priv_key); /* In the handshake step, we blindly try to step both the client and * server ends of the handshake. As NSS stores the contents of what we're * supposed to be sending, as long as our buffers are of "reasonable" * size, we'll be able to step one of the two sides until something useful * happens. */ printf("Trying handshake...\n"); int count = 0; while (!is_finished(c_nspr, s_nspr)) { printf("Client Handshake:\n"); if (SSL_ForceHandshake(c_nspr) != SECSuccess) { const PRErrorCode err = PR_GetError(); if (err != PR_WOULD_BLOCK_ERROR) { fprintf(stderr, "error: SSL_ForceHandshake error %d: %s\n", err, PR_ErrorToName(err)); exit(1); } } printf("\n\nServer Handshake:\n"); if (SSL_ForceHandshake(s_nspr) != SECSuccess) { const PRErrorCode err = PR_GetError(); if (err != PR_WOULD_BLOCK_ERROR) { fprintf(stderr, "error: SSL_ForceHandshake error %d: %s\n", err, PR_ErrorToName(err)); exit(1); } } printf("\n\n"); count += 1; if (count >= 40) { fprintf(stderr, "error: unable to make progress after %d steps!\n", count); exit(1); } } /* Send a test message from client -> server to ensure that the connection * truly is ready. */ /* Note: we don't handle E_WOULDBLOCK here as our messages are small. */ printf("Send a message from the client to the server...\n"); size_t buf_size = 1025; char *buf = calloc(buf_size, sizeof(char)); char *buf2 = calloc(buf_size, sizeof(char)); char *client_message = "Cooking MCs"; char *server_message = "like a pound of bacon"; memcpy(buf, client_message, strlen(client_message)); PRInt32 ret = PR_Write(c_nspr, buf, strlen(buf)); if (ret < 0) { const PRErrorCode err = PR_GetError(); fprintf(stderr, "error: PR_Write error %d: %s\n", err, PR_ErrorToName(err)); exit(1); } ret = PR_Read(s_nspr, buf2, buf_size - 1); if (ret < 0) { const PRErrorCode err = PR_GetError(); fprintf(stderr, "error: PR_Read error %d: %s\n", err, PR_ErrorToName(err)); exit(1); } printf("Received message from client: %s [len: %d]\n", buf2, ret); printf("\n\n"); /* Send a message back to confirm we received it! */ printf("Send a message from the server to the client...\n"); memcpy(buf, server_message, strlen(server_message)); ret = PR_Write(s_nspr, buf, strlen(buf)); if (ret < 0) { const PRErrorCode err = PR_GetError(); fprintf(stderr, "error: PR_Write error %d: %s\n", err, PR_ErrorToName(err)); exit(1); } memset(buf2, 0, buf_size); ret = PR_Read(c_nspr, buf2, buf_size - 1); if (ret < 0) { const PRErrorCode err = PR_GetError(); fprintf(stderr, "error: PR_Read error %d: %s\n", err, PR_ErrorToName(err)); exit(1); } printf("Received message from client: %s [len: %d]\n", buf2, ret); /* Close the client and then the server end of the connection. */ ret = PR_Shutdown(c_nspr, PR_SHUTDOWN_BOTH); if (ret < 0) { const PRErrorCode err = PR_GetError(); fprintf(stderr, "error: PR_Shutdown client error %d: %s\n", err, PR_ErrorToName(err)); exit(1); } ret = PR_Shutdown(s_nspr, PR_SHUTDOWN_BOTH); if (ret < 0) { const PRErrorCode err = PR_GetError(); fprintf(stderr, "error: PR_Shutdown server error %d: %s\n", err, PR_ErrorToName(err)); exit(1); } /* Closes the underlying POSIX file descriptors */ PR_Close(c_nspr); PR_Close(s_nspr); /* Free the buffers and their contents */ jb_free(c_read_buf); jb_free(c_write_buf); free(buf); free(buf2); SECKEY_DestroyPrivateKey(priv_key); NSS_Shutdown(); return 0; } jss-5.0.0/src/test/java/org/mozilla/jss/tests/TestCertificateApprovalCallback.java000066400000000000000000000060651412550063600302610ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.util.Enumeration; import org.mozilla.jss.crypto.InternalCertificate; import org.mozilla.jss.ssl.SSLCertificateApprovalCallback; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This is a test implementation of the certificate approval callback which * gets invoked when the server presents a certificate which is not * trusted by the client. * * Note this implementation accepts all certificates! */ public class TestCertificateApprovalCallback implements SSLCertificateApprovalCallback { public static Logger logger = LoggerFactory.getLogger(TestCertificateApprovalCallback.class); @Override public boolean approve( org.mozilla.jss.crypto.X509Certificate servercert, SSLCertificateApprovalCallback.ValidityStatus status) { SSLCertificateApprovalCallback.ValidityItem item; logger.debug("in TestCertificateApprovalCallback.approve()"); /* dump out server cert details */ logger.debug("Peer cert details:"); logger.debug(" subject: " + servercert.getSubjectDN()); logger.debug(" issuer: " + servercert.getIssuerDN()); logger.debug(" serial: " + servercert.getSerialNumber()); /* iterate through all the problems */ boolean trust_the_server_cert=false; Enumeration errors = status.getReasons(); int i=0; while (errors.hasMoreElements()) { i++; item = errors.nextElement(); logger.debug("item "+i+ " reason="+item.getReason()+ " depth="+item.getDepth()); org.mozilla.jss.crypto.X509Certificate cert = item.getCert(); if (item.getReason() == SSLCertificateApprovalCallback.ValidityStatus.UNTRUSTED_ISSUER) { trust_the_server_cert = true; } logger.debug(" cert details:"); logger.debug(" subject: " + cert.getSubjectDN()); logger.debug(" issuer: " + cert.getIssuerDN()); logger.debug(" serial: " + cert.getSerialNumber()); } if (trust_the_server_cert) { logger.debug("importing certificate."); try { InternalCertificate newcert = org.mozilla.jss.CryptoManager.getInstance(). importCertToPerm(servercert,"testnick"); newcert.setSSLTrust(InternalCertificate.TRUSTED_PEER | InternalCertificate.VALID_PEER); } catch (Exception e) { System.out.println("thrown exception: "+e); } } /* allow the connection to continue. */ /* returning false here would abort the connection */ /* don't do this in production code! */ return true; } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/TestCmac.java000066400000000000000000000065551412550063600235640ustar00rootroot00000000000000package org.mozilla.jss.tests; import java.util.Arrays; import java.util.Base64; import java.security.Key; import javax.crypto.*; import javax.crypto.spec.*; import org.mozilla.jss.*; import org.mozilla.jss.crypto.*; import org.mozilla.jss.util.*; public class TestCmac { private static final byte[] NIST_128 = Base64.getDecoder().decode("K34VFiiu0qar9xWICc9PPA=="); private static final byte[] NIST_192 = Base64.getDecoder().decode("jnOw99oOZFLIEPMrgJB55WL46tJSLGt7"); private static final byte[] NIST_256 = Base64.getDecoder().decode("YD3rEBXKcb4rc67whX13gR81LAc7YQjXLZgQowkU3/Q="); public static void main(String[] args) throws Exception { CryptoManager cm = CryptoManager.getInstance(); CryptoToken tok = cm.getInternalKeyStorageToken(); PasswordCallback cb = new FilePasswordCallback(args[1]); tok.login(cb); testNISTExamples(); } /* * The following test vectors come from NIST's Examples with Intermediate * Values page: * https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines/example-values * * These are the same vectors utilized by NSS in: * gtests/freebl_gtest/cmac_unittests.cc * * These same vectors are also found in FRC 4493, Section 4. */ public static void testNISTExamples() throws Exception { byte[] all_input = Base64.getDecoder().decode("a8G+4i5An5bpPX4Rc5MXKq4tilceA6ycnrdvrEWvjlEwyBxGo1zkEeX7wRkaClLv9p8kRd9PmxetK0F75mw3EA=="); int[] input_lengths = new int[] { 0, 16, 20, 64}; byte[][] all_expected = new byte[][] { Base64.getDecoder().decode("ux1pKelZNyh/o30Sm3VnRg=="), Base64.getDecoder().decode("BwoWtGtNQUT3m92d0EoofA=="), Base64.getDecoder().decode("fYVEnqbqGcgjp794g3363g=="), Base64.getDecoder().decode("UfC+v347nZL8SXQXeTY8/g=="), Base64.getDecoder().decode("0X3fRq2qzeUxysSD3nqTZw=="), Base64.getDecoder().decode("npmnvzHnEJAGYvZeYXxRhA=="), Base64.getDecoder().decode("PXXBlO2WBwREqfp+x0Ds+A=="), Base64.getDecoder().decode("odXfDu15D3lNd1iWWfOaEQ=="), Base64.getDecoder().decode("Aoli9ht7+J78a1UfRmfZgw=="), Base64.getDecoder().decode("KKcCP0Uuj4K9S/KNjDfDXA=="), Base64.getDecoder().decode("FWcn3Ah4lEoCPB/gO61tkw=="), Base64.getDecoder().decode("4ZkhkFSfbtVpaiwFbDFUEA==") }; for (int i = 0; i < all_expected.length; i++) { byte[] key = getKey(i); byte[] input = Arrays.copyOf(all_input, input_lengths[i % input_lengths.length]); byte[] expected = all_expected[i]; testCMAC(key, input, expected); } } public static byte[] getKey(int index) { if (index < 4) { return NIST_128; } else if (index < 8) { return NIST_192; } else if (index < 12) { return NIST_256; } return null; } public static void testCMAC(byte[] key_bytes, byte[] input, byte[] expected) throws Exception { Mac mac = Mac.getInstance("AES_CMAC", "Mozilla-JSS"); SecretKeyFactory factory = SecretKeyFactory.getInstance("AES", "Mozilla-JSS"); Key key = factory.generateSecret(new SecretKeySpec(key_bytes, "AES")); mac.init(key); byte[] actual = mac.doFinal(input); assert(Arrays.equals(actual, expected)); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/TestGlobalReference.java000066400000000000000000000024151412550063600257270ustar00rootroot00000000000000package org.mozilla.jss.tests; import org.mozilla.jss.util.*; public class TestGlobalReference { public static void main(String[] args) throws Exception { String arg = "Something"; for (int i = 0; i < 100; i++) { GlobalRefProxy proxy = new GlobalRefProxy(arg); // This should free the global reference. proxy.close(); // This call makes sure the NativeProxy was removed from the // reference tracker; otherwise, the JVM would crash due to a // double free. proxy.close(); // This call makes sure clear behaves correctly after a call to // close was also made. proxy.clear(); } for (int i = 1; i <= 4; i++) { // This attempts to provoke the GC into running, hopefully // executing GlobalRefProxy.finalize(...) on the above objects. // This will be another attempt to trigger a double free, but // we shouldn't crash. System.gc(); Thread.sleep(i * 500); } // Since we didn't initialize JSS and we freed all our GlobalRefProxy // instances we created, we expect the registry to be empty. NativeProxy.assertRegistryEmpty(); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/TestKBKDF.java000066400000000000000000000131521412550063600235310ustar00rootroot00000000000000package org.mozilla.jss.tests; import java.util.Arrays; import java.util.Base64; import javax.crypto.*; import javax.crypto.spec.*; import org.mozilla.jss.*; import org.mozilla.jss.crypto.*; import org.mozilla.jss.pkcs11.*; public class TestKBKDF { public static void main(String[] args) throws Exception { CryptoManager cm = CryptoManager.getInstance(); TokenSupplier ts = TokenSupplierManager.getTokenSupplier(); ts.setThreadToken(cm.getInternalCryptoToken()); testCounterKDFNistCMAC(); testFeedbackKDFNistCMAC(); testPipelineKDFNistCMAC(); } public static void testCounterKDFNistCMAC() throws Exception { javax.crypto.KeyGenerator kg = javax.crypto.KeyGenerator.getInstance("KbkdfCounterData", "Mozilla-JSS"); SecretKeyFactory skf = SecretKeyFactory.getInstance("AES", "Mozilla-JSS"); byte[] prf_key_bytes = Base64.getDecoder().decode("3/HlCsC2ncQPEFHUbCsGnA=="); SecretKey prf_key = skf.generateSecret(new SecretKeySpec(prf_key_bytes, "AES")); SymmetricKey smkey = ((SecretKeyFacade)prf_key).key; CryptoToken token = smkey.getOwningToken(); PK11Token tkn = (PK11Token)token; KBKDFCounterParams kcp = new KBKDFCounterParams(); kcp.setPRF(PKCS11Algorithm.CKM_AES_CMAC); kcp.setPRFKey(prf_key); kcp.setKeySize(16); kcp.setDerivedKeyAlgorithm(PKCS11Algorithm.CKM_SHA_512_HMAC); kcp.addParameter(new KBKDFIterationVariableParam(true, 8)); byte[] byte_array_param = Base64.getDecoder().decode("wW5uAsWj3MjXi5rBMGh3dhMQRVtOQUaZUdnmwiRaBksz/Yw7ASA6eCRIW/CmQGDEZItwfSYHk1aZMW6l"); kcp.addParameter(new KBKDFByteArrayParam(byte_array_param)); // RHEL 8.2 doesn't support additional derived keys. /*KBKDFDerivedKey kdk = new KBKDFDerivedKey(); kdk.addAttribute(new CKAClass.Data()); kdk.addAttribute(new CKAUsage.Encrypt()); kdk.addAttribute(new CKAValueLen(16)); kcp.addAdditionalDerivedKey(kdk);*/ kg.init(kcp); SecretKey key = kg.generateKey(); assert(key != null); byte[] encoded = key.getEncoded(); byte[] expected = Base64.getDecoder().decode("i+jwhps8C6l7cYY9G594Ew=="); assert(Arrays.equals(encoded, expected)); /*SecretKey other_key = kdk.getKey(key, PKCS11Constants.CKM_SHA512_HMAC, true); byte[] other_encoded = other_key.getEncoded(); byte[] other_expected = Base64.getDecoder().decode("DMdy/9fjofZGZMe3xhxlEg=="); assert(Arrays.equals(encoded, expected));*/ } public static void testFeedbackKDFNistCMAC() throws Exception { javax.crypto.KeyGenerator kg = javax.crypto.KeyGenerator.getInstance("KbkdfFeedbackData", "Mozilla-JSS"); SecretKeyFactory skf = SecretKeyFactory.getInstance("AES", "Mozilla-JSS"); byte[] prf_key_bytes = Base64.getDecoder().decode("ILu+NunIPFGETNMenCCUMQ=="); SecretKey prf_key = skf.generateSecret(new SecretKeySpec(prf_key_bytes, "AES")); SymmetricKey smkey = ((SecretKeyFacade)prf_key).key; CryptoToken token = smkey.getOwningToken(); PK11Token tkn = (PK11Token)token; KBKDFFeedbackParams kfp = new KBKDFFeedbackParams(); kfp.setPRF(PKCS11Algorithm.CKM_AES_CMAC); kfp.setPRFKey(prf_key); kfp.setKeySize(64); kfp.setDerivedKeyAlgorithm(PKCS11Algorithm.CKM_SHA_512_HMAC); kfp.addParameter(new KBKDFOptionalCounterParam(true, 8)); kfp.addParameter(new KBKDFIterationVariableParam()); byte[] byte_array_param = Base64.getDecoder().decode("61B6/2n3fqtqugQgNKXLGZDXenzXKkmE8/skL7RM4PuUnpnZXYHlcQm31c03RqMhbEej"); kfp.addParameter(new KBKDFByteArrayParam(byte_array_param)); byte[] iv = Base64.getDecoder().decode("KPKKUyw744XXLsUyE2f4tg=="); kfp.setInitialValue(iv); kg.init(kfp); SecretKey key = kg.generateKey(); assert(key != null); byte[] encoded = key.getEncoded(); byte[] expected = Base64.getDecoder().decode("J3pHPT9RSvP3YKI4M0PA63mfeanI8fMds34RBHhtO6IMn7KkLSmXzKt/eaXBnwlHBtMuCbzk93rtYWKvCNidHQ=="); assert(Arrays.equals(encoded, expected)); } public static void testPipelineKDFNistCMAC() throws Exception { javax.crypto.KeyGenerator kg = javax.crypto.KeyGenerator.getInstance("KbkdfPipelineData", "Mozilla-JSS"); SecretKeyFactory skf = SecretKeyFactory.getInstance("AES", "Mozilla-JSS"); byte[] prf_key_bytes = Base64.getDecoder().decode("xiVNld0QjpuyngBT3e7DUQ=="); SecretKey prf_key = skf.generateSecret(new SecretKeySpec(prf_key_bytes, "AES")); SymmetricKey smkey = ((SecretKeyFacade)prf_key).key; CryptoToken token = smkey.getOwningToken(); PK11Token tkn = (PK11Token)token; KBKDFPipelineParams kcp = new KBKDFPipelineParams(); kcp.setPRF(PKCS11Algorithm.CKM_AES_CMAC); kcp.setPRFKey(prf_key); kcp.setKeySize(64); kcp.setDerivedKeyAlgorithm(PKCS11Algorithm.CKM_SHA_512_HMAC); kcp.addParameter(new KBKDFOptionalCounterParam(true, 8)); kcp.addParameter(new KBKDFIterationVariableParam()); byte[] byte_array_param = Base64.getDecoder().decode("IvSY/JuNS3IYi84wuph1/CsOs/52h02FQm5uWzsjfJ9EXy2iCmCrGJgC4sFSxKNgKqNC"); kcp.addParameter(new KBKDFByteArrayParam(byte_array_param)); kg.init(kcp); SecretKey key = kg.generateKey(); assert(key != null); byte[] encoded = key.getEncoded(); byte[] expected = Base64.getDecoder().decode("HhM6lS31WhHuA4EgN19h58AWKELIFxYGk7HzncC3lbxvNpHbd1zzr0sKn2n+y+mWef1LSHPdp0P1xqLS6HPybQ=="); assert(Arrays.equals(encoded, expected)); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/TestKeyGen.java000066400000000000000000000205371412550063600240770ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** * Note: when this program is run, it must have a key3.db WITH A PASSWORD * SET in the directory specified by the argument. The first time the * program is run, a key3.db file will be created, but it will not have * a password. This will result in the error: * Token error: org.mozilla.jss.crypto.TokenException: unable to login to token * * To create a database with a password, you can: * use the modutil or keyutil tool, * use the JSS API CryptoToken.changePassword() to set the password * run the test 'TokenAccessTest' * which will create db with a password. */ package org.mozilla.jss.tests; import java.math.BigInteger; import java.security.interfaces.DSAParams; import java.security.interfaces.DSAPublicKey; import java.security.interfaces.RSAPublicKey; import java.util.Enumeration; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.KeyPairAlgorithm; import org.mozilla.jss.crypto.RSAParameterSpec; import org.mozilla.jss.pkcs11.PK11KeyPairGenerator; import org.mozilla.jss.util.Base64OutputStream; public class TestKeyGen { public static void main(String[] args) { try { CryptoManager manager; java.security.KeyPair keyPair; Base64OutputStream base64; if(args.length != 2) { System.err.println("Usage: java org.mozilla.jss.pkcs11." + "TestKeyGen "); System.exit(1); } manager = CryptoManager.getInstance(); manager.setPasswordCallback( new FilePasswordCallback(args[1]) ); Enumeration tokens = manager.getTokensSupportingAlgorithm(KeyPairAlgorithm.RSA); System.out.println("The following tokens support RSA keygen:"); while(tokens.hasMoreElements()) { System.out.println("\t"+ tokens.nextElement().getName() ); } tokens = manager.getTokensSupportingAlgorithm(KeyPairAlgorithm.DSA); System.out.println("The following tokens support DSA keygen:"); while(tokens.hasMoreElements()) { System.out.println("\t"+ tokens.nextElement().getName() ); } RSAPublicKey rsaPubKey; DSAPublicKey dsaPubKey; DSAParams dsaParams; RSAParameterSpec rsaParams; java.security.KeyPairGenerator kpg = java.security.KeyPairGenerator.getInstance("RSA", "Mozilla-JSS"); // 512-bit RSA with default exponent System.out.println("Generating 512-bit RSA KeyPair!"); for (int cntr=0; cntr<5; cntr++ ) { try { kpg.initialize(512); keyPair = kpg.genKeyPair(); assert( keyPair.getPublic() instanceof RSAPublicKey); rsaPubKey = (RSAPublicKey) keyPair.getPublic(); System.out.println("Generated 512-bit RSA KeyPair!"); System.out.println("Modulus: "+rsaPubKey.getModulus()); System.out.println("Exponent: "+rsaPubKey.getPublicExponent()); break; } catch (org.mozilla.jss.crypto.TokenRuntimeException TRExRSA512) { if (cntr==5) { System.out.println("Generation of 512-bit RSA KeyPair Failed\n"); TRExRSA512.printStackTrace(); } } } // 1024-bit RSA with default exponent System.out.println("Generating 1024-bit RSA KeyPair!"); for (int cntr=0; cntr<5; cntr++ ) { try { kpg.initialize(1024); keyPair = kpg.genKeyPair(); assert( keyPair.getPublic() instanceof RSAPublicKey); rsaPubKey = (RSAPublicKey) keyPair.getPublic(); System.out.println("Generated 1024-bit RSA KeyPair!"); System.out.println("Modulus: "+rsaPubKey.getModulus()); System.out.println("Exponent: "+rsaPubKey.getPublicExponent()); break; } catch (org.mozilla.jss.crypto.TokenRuntimeException TRExRSA1024) { if (cntr==5) { System.out.println("Generation of 1024-bit RSA KeyPair Failed\n"); TRExRSA1024.printStackTrace(); } } } // 512-bit RSA with exponent = 3 System.out.println("Generating 512-bit RSA KeyPair with public exponent=3!"); for (int cntr=0; cntr<5; cntr++ ) { try { rsaParams = new RSAParameterSpec(512, BigInteger.valueOf(3)); kpg.initialize(rsaParams); keyPair = kpg.genKeyPair(); assert( keyPair.getPublic() instanceof RSAPublicKey); rsaPubKey = (RSAPublicKey) keyPair.getPublic(); System.out.println("Generated 512-bit RSA KeyPair with public exponent=3!"); System.out.println("Modulus: "+rsaPubKey.getModulus()); System.out.println("Exponent: "+rsaPubKey.getPublicExponent()); break; } catch (org.mozilla.jss.crypto.TokenRuntimeException TRExRSA512Exp3) { if (cntr==5) { System.out.println("Generation of 512-bit RSA KeyPair with public exponent=3 Failed\n"); TRExRSA512Exp3.printStackTrace(); } } } // 512-bit DSA System.out.println("Generating 512-bit DSA KeyPair!"); kpg = java.security.KeyPairGenerator.getInstance("DSA", "Mozilla-JSS"); for (int cntr=0; cntr<5; cntr++ ) { try { kpg.initialize(512); keyPair = kpg.genKeyPair(); assert( keyPair.getPublic() instanceof DSAPublicKey); dsaPubKey = (DSAPublicKey) keyPair.getPublic(); System.out.println("Generated 512-bit DSA KeyPair!"); dsaParams = dsaPubKey.getParams(); System.out.println("P: "+dsaParams.getP()); System.out.println("Q: "+dsaParams.getQ()); System.out.println("G: "+dsaParams.getG()); System.out.println("Y: "+dsaPubKey.getY()); break; } catch (org.mozilla.jss.crypto.TokenRuntimeException TRExDSA512) { if (cntr==5) { System.out.println("Generation of 512-bit DSA KeyPair Failed\n"); TRExDSA512.printStackTrace(); } } } // 1024-bit DSA, passing in PQG params System.out.println("Generating 1024-bit DSA KeyPair with PQG params!"); for (int cntr=0; cntr<5; cntr++ ) { try { kpg.initialize(PK11KeyPairGenerator.PQG1024); keyPair = kpg.genKeyPair(); assert( keyPair.getPublic() instanceof DSAPublicKey); dsaPubKey = (DSAPublicKey) keyPair.getPublic(); System.out.println("Generated 1024-bit DSA KeyPair with PQG params!"); dsaParams = dsaPubKey.getParams(); System.out.println("P: "+dsaParams.getP()); System.out.println("Q: "+dsaParams.getQ()); System.out.println("G: "+dsaParams.getG()); System.out.println("Y: "+dsaPubKey.getY()); break; } catch (org.mozilla.jss.crypto.TokenRuntimeException TRExDSA1024) { if (cntr==5) { System.out.println("Generation of 1024-bit DSA KeyPair with PQG params Failed\n"); TRExDSA1024.printStackTrace(); } } } // 256-bit EC kpg = java.security.KeyPairGenerator.getInstance("EC", "Mozilla-JSS"); kpg.initialize(256); keyPair = kpg.genKeyPair(); System.out.println("Generated 256-bit EC KeyPair!"); kpg.initialize(384); keyPair = kpg.genKeyPair(); System.out.println("Generated 384-bit EC KeyPair!"); kpg.initialize(521); keyPair = kpg.genKeyPair(); System.out.println("Generated 521-bit EC KeyPair!"); System.out.println("TestKeyGen passed"); System.exit(0); } catch (Exception e) { e.printStackTrace(); System.exit(1); } } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/TestPKCS11Constants.java000066400000000000000000000060421412550063600255070ustar00rootroot00000000000000package org.mozilla.jss.tests; import java.lang.reflect.*; import java.util.*; public class TestPKCS11Constants { /** * This test compares the value of the PKCS11Constants that is maintained * by JSS against the values maintained by Sun in the equivalent methods. * * Note that this should only be run on JDK8, the last JDK to ship an * accessible set of PKCS11Constants */ public static void main(String[] args) throws Exception { // Query the two classes to get references to their definitions. Class jss = Class.forName("org.mozilla.jss.pkcs11.PKCS11Constants"); Class sun = Class.forName("sun.security.pkcs11.wrapper.PKCS11Constants"); assert(!jss.equals(sun)); // Get lists of all fields; lets us call the reflection seervices // once as they're likely slow. Field[] jss_fields = jss.getDeclaredFields(); Field[] sun_fields = sun.getDeclaredFields(); // To easily access the fields, build a HashMap of String->Field, // and maintain a set of all known field names. HashMap jss_map = new HashMap(); HashMap sun_map = new HashMap(); HashSet keys = new HashSet(); for (Field field : jss_fields) { jss_map.put(field.getName(), field); keys.add(field.getName()); } for (Field field : sun_fields) { sun_map.put(field.getName(), field); keys.add(field.getName()); } // For pretty output, sort keys first... String[] keys_sorted = new String[keys.size()]; keys_sorted = keys.toArray(keys_sorted); Arrays.sort(keys_sorted); for (String key : keys_sorted) { // If the field is present in both, validate that the value // is the same across JSS and Sun implementation. Otherwise, // output which implementation it is present in. if (jss_map.containsKey(key) && sun_map.containsKey(key)) { Field jss_field = jss_map.get(key); Field sun_field = sun_map.get(key); // Validate that types are correct before accessing... assert(jss_field.getType() == long.class); assert(sun_field.getType() == long.class); if (jss_field.getLong(null) != sun_field.getLong(null)) { System.err.println("Symbol: " + key + " - NOT OK!!\n"); System.err.println("\tJSS: " + jss_field.getLong(null)); System.err.println("\tSun: " + sun_field.getLong(null)); } assert(jss_field.getLong(null) == sun_field.getLong(null)); System.out.println("Field: " + key + " - OK"); } else if (jss_map.containsKey(key)) { System.err.println("Field: " + key + " - only JSS"); } else if (sun_map.containsKey(key)) { System.err.println("Field: " + key + " - only Sun"); } } } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/TestPRFD.java000066400000000000000000000062571412550063600234530ustar00rootroot00000000000000package org.mozilla.jss.tests; import org.mozilla.jss.nss.PR; import org.mozilla.jss.nss.PRErrors; import org.mozilla.jss.nss.PRFDProxy; public class TestPRFD { public static void TestPROpenNoCreate() { String name = "path_which_should_not_exist_on_any_reasonable_system"; PRFDProxy fd = PR.Open(name, 0x02, 00644); assert(fd == null); } public static void TestPROpenClose() { PRFDProxy fd = PR.Open("results/prfd_open_close", 0x04 | 0x08, 00644); assert(fd != null); assert(PR.Close(fd) == PR.SUCCESS); } public static void TestPROpenWriteClose() { PRFDProxy fd = PR.Open("results/prfd_open_write_close", 0x04 | 0x08, 00644); assert(fd != null); byte[] data = {0x2a, 0x20, 0x2a, 0x20}; assert(PR.Write(fd, data) == 4); assert(PR.Close(fd) == PR.SUCCESS); } public static void TestPRRead() { byte[] data = {0x2a, 0x20, 0x2a, 0x20}; PRFDProxy fd = PR.Open("results/prfd_open_write_close", 0x04, 00644); assert(fd != null); byte[] read_data = PR.Read(fd, 10); assert(read_data != null); assert(read_data.length == data.length); for (int i = 0; i < data.length; i++) { assert(read_data[i] == data[i]); } assert(PR.Close(fd) == PR.SUCCESS); } public static void TestPREmptyRead() { PRFDProxy fd = PR.Open("results/prfd_open_close", 0x04, 00644); assert(fd != null); byte[] read_data = PR.Read(fd, 10); assert(read_data == null || read_data.length == 0); assert(PR.Close(fd) == PR.SUCCESS); } public static void TestNewTCPSocket() { PRFDProxy fd = PR.NewTCPSocket(); assert(fd != null); } public static void TestShutdown() { PRFDProxy fd = PR.NewTCPSocket(); assert(fd != null); PR.Shutdown(fd, PR.SHUTDOWN_RCV); PR.Shutdown(fd, PR.SHUTDOWN_SEND); PR.Shutdown(fd, PR.SHUTDOWN_BOTH); assert(PR.Close(fd) == PR.SUCCESS); } public static void TestConstants() { // Test to ensure constants present System.out.println("PR.SHUTDOWN_RCV: " + PR.SHUTDOWN_RCV); System.out.println("PR.SHUTDOWN_SEND: " + PR.SHUTDOWN_SEND); System.out.println("PR.SHUTDOWN_BOTH: " + PR.SHUTDOWN_BOTH); assert(PR.ErrorToName(PRErrors.WOULD_BLOCK_ERROR).equals("PR_WOULD_BLOCK_ERROR")); } public static void main(String[] args) { System.loadLibrary("jss"); System.out.println("Calling TestPROpenNoCreate()..."); TestPROpenNoCreate(); System.out.println("Calling TestPROpenClose()..."); TestPROpenClose(); System.out.println("Calling TestPROpenWriteClose()..."); TestPROpenWriteClose(); System.out.println("Calling TestPRRead()..."); TestPRRead(); System.out.println("Calling TestPREmptyRead()..."); TestPREmptyRead(); System.out.println("Calling TestNewTCPSocket()..."); TestNewTCPSocket(); System.out.println("Calling TestShutdown()..."); TestShutdown(); System.out.println("Calling TestConstants()..."); TestConstants(); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/TestRawSSL.java000066400000000000000000000133241412550063600240240ustar00rootroot00000000000000package org.mozilla.jss.tests; import org.mozilla.jss.nss.PR; import org.mozilla.jss.nss.PRFDProxy; import org.mozilla.jss.nss.SSL; import org.mozilla.jss.nss.SSLChannelInfo; import org.mozilla.jss.nss.SSLFDProxy; import org.mozilla.jss.nss.SSLPreliminaryChannelInfo; import org.mozilla.jss.nss.SecurityStatusResult; import org.mozilla.jss.ssl.SSLCipher; public class TestRawSSL { public static void TestSSLImportFD() throws Exception { PRFDProxy fd = PR.NewTCPSocket(); assert(fd != null); SSLFDProxy ssl_fd = SSL.ImportFD(null, fd); assert(ssl_fd != null); assert(PR.Close(ssl_fd) == PR.SUCCESS); } public static void TestSSLOptions() throws Exception { PRFDProxy fd = PR.NewTCPSocket(); assert(fd != null); SSLFDProxy ssl_fd = SSL.ImportFD(null, fd); assert(ssl_fd != null); // 8 == SSL_ENABLE_SSL3; disable it assert(SSL.OptionSet(ssl_fd, 8, 0) == SSL.SECSuccess); // Validate that the set worked. assert(SSL.OptionGet(ssl_fd, 8) == SSL.SECSuccess); // Renable SSL_ENABLE_SSL3 and validate it worked assert(SSL.OptionSet(ssl_fd, 8, 1) == SSL.SECSuccess); assert(SSL.OptionGet(ssl_fd, 8) == 1); // Ensure that setting an invalid option fails assert(SSL.OptionSet(ssl_fd, 799999, 0) != SSL.SECSuccess); // Ensure that getting an invalid option fails try { SSL.OptionGet(ssl_fd, 79999999); assert(false); } catch (Exception e) { assert(true); } assert(PR.Close(ssl_fd) == PR.SUCCESS); } public static void TestSSLCipherPref() throws Exception { PRFDProxy fd = PR.NewTCPSocket(); assert(fd != null); SSLFDProxy ssl_fd = SSL.ImportFD(null, fd); assert(ssl_fd != null); int cipher = SSLCipher.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384.getID(); // Ensure that setting a ciphersuite works correctly assert(SSL.CipherPrefSet(ssl_fd, cipher, false) == SSL.SECSuccess); assert(SSL.CipherPrefGet(ssl_fd, cipher) == false); assert(SSL.CipherPrefSet(ssl_fd, cipher, true) == SSL.SECSuccess); assert(SSL.CipherPrefGet(ssl_fd, cipher) == true); // Ensure that using an invalid ciphersuite fails. assert(SSL.CipherPrefSet(ssl_fd, 0x999999, false) == SSL.SECFailure); try { SSL.CipherPrefGet(ssl_fd, 0x999999); assert(false); } catch (Exception e) { assert(true); } assert(PR.Close(ssl_fd) == PR.SUCCESS); } public static void TestSSLSetURL() throws Exception { PRFDProxy fd = PR.NewTCPSocket(); assert(fd != null); SSLFDProxy ssl_fd = SSL.ImportFD(null, fd); assert(ssl_fd != null); assert(SSL.SetURL(ssl_fd, "https://google.com") == SSL.SECSuccess); assert(PR.Close(ssl_fd) == PR.SUCCESS); } public static void TestSSLSecurityStatus() throws Exception { PRFDProxy fd = PR.NewTCPSocket(); assert(fd != null); SSLFDProxy ssl_fd = SSL.ImportFD(null, fd); assert(ssl_fd != null); SecurityStatusResult r = SSL.SecurityStatus(ssl_fd); assert(r != null); assert(r.on == 0); // Validate toString works System.out.println(r.toString()); assert(PR.Close(ssl_fd) == PR.SUCCESS); } public static void TestSSLGetChannelInfo() throws Exception { PRFDProxy fd = PR.NewTCPSocket(); assert(fd != null); SSLFDProxy ssl_fd = SSL.ImportFD(null, fd); assert(ssl_fd != null); SSLChannelInfo r = SSL.GetChannelInfo(ssl_fd); assert(r != null); assert(r.getProtocolVersion() == null); System.out.println(r.toString()); assert(PR.Close(ssl_fd) == PR.SUCCESS); } public static void TestSSLGetPreliminaryChannelInfo() throws Exception { PRFDProxy fd = PR.NewTCPSocket(); assert(fd != null); SSLFDProxy ssl_fd = SSL.ImportFD(null, fd); assert(ssl_fd != null); SSLPreliminaryChannelInfo r = SSL.GetPreliminaryChannelInfo(ssl_fd); assert(r != null); assert(r.haveProtocolVersion() == false); assert(r.haveCipherSuite() == false); assert(r.haveZeroRttCipherSuite() == false); assert(r.havePeerAuth() == false); System.out.println(r.toString()); assert(PR.Close(ssl_fd) == PR.SUCCESS); } public static void TestSSLResetHandshake() throws Exception { PRFDProxy fd = PR.NewTCPSocket(); assert(fd != null); SSLFDProxy ssl_fd = SSL.ImportFD(null, fd); assert(SSL.ResetHandshake(ssl_fd, false) == SSL.SECSuccess); assert(PR.Close(ssl_fd) == PR.SUCCESS); } public static void main(String[] args) throws Exception { System.loadLibrary("jss"); if (args.length != 1) { System.out.println("Usage: TestRawSSL /path/to/nssdb"); System.exit(1); } System.out.println("Calling TestSSLImportFD()..."); TestSSLImportFD(); System.out.println("Calling TestSSLOptions()..."); TestSSLOptions(); System.out.println("Calling TestSSLSetURL()..."); TestSSLSetURL(); System.out.println("Calling TestSSLCipherPref()..."); TestSSLCipherPref(); System.out.println("Calling TestSSLSecurityStatus()..."); TestSSLSecurityStatus(); System.out.println("Calling TestSSLGetChannelInfo()..."); TestSSLGetChannelInfo(); System.out.println("Calling TestSSLGetPreliminaryChannelInfo()..."); TestSSLGetPreliminaryChannelInfo(); System.out.println("Calling TestSSLResetHandshake()..."); TestSSLResetHandshake(); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/TestSDR.java000066400000000000000000000062651412550063600233470ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.security.*; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.crypto.*; import org.mozilla.jss.SecretDecoderRing.*; import javax.crypto.*; /** * Secret Decoder ring tests. */ public class TestSDR { public static final EncryptionAlgorithm encAlg = EncryptionAlgorithm.DES3_CBC; public static final KeyGenAlgorithm keyGenAlg = KeyGenAlgorithm.DES3; public static void main(String[] args) throws Exception { if( args.length != 2 ) { throw new Exception("Usage: java TestSDR "); } CryptoManager cm = CryptoManager.getInstance(); cm.setPasswordCallback( new FilePasswordCallback(args[1]) ); CryptoToken ksToken = cm.getInternalKeyStorageToken(); // // test key management // KeyManager km = new KeyManager(ksToken); byte[] keyID = km.generateKey(keyGenAlg, 0); System.out.println("Successfully generated key"); SecretKey key = km.lookupKey(encAlg, keyID); if( key == null ) { throw new Exception("Error: generated key not found"); } System.out.println("Successfully looked up key"); km.deleteKey(keyID); System.out.println("Successfully deleted key"); key = km.lookupKey(encAlg, keyID); if( key != null ) { throw new Exception("Deleted key still found"); } System.out.println("Good: deleted key not found"); // // test encryption/decryption // keyID = km.generateKey(keyGenAlg, 0); Encryptor encryptor = new Encryptor(ksToken, keyID, encAlg); byte[] plaintext = "Hello, world!".getBytes("UTF-8"); byte[] ciphertext = encryptor.encrypt(plaintext); System.out.println("Successfully encrypted plaintext"); Decryptor decryptor = new Decryptor(ksToken); byte[] recovered = decryptor.decrypt(ciphertext); System.out.println("Decrypted ciphertext"); if( plaintext.length != recovered.length ) { throw new Exception( "Recovered plaintext does not match original plaintext"); } for(int i=0; i < plaintext.length; ++i) { if( plaintext[i] != recovered[i] ) { throw new Exception( "Recovered plaintext does not match original plaintext"); } } System.out.println("Decrypted ciphertext matches original plaintext"); // delete the key and try to decrypt. Decryption should fail. km.deleteKey(keyID); try { recovered = decryptor.decrypt(ciphertext); throw new Exception( "Error: successfully decrypted with deleted key"); } catch (InvalidKeyException ike) { } System.out.println( "Good: as expected did not decrypt plaintext with a " + "deleted key"); System.out.println("TestSDR: Success"); System.exit(0); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/TestSSLEngine.java000066400000000000000000001224511412550063600245020ustar00rootroot00000000000000package org.mozilla.jss.tests; import java.nio.ByteBuffer; import java.security.KeyStore; import java.util.ArrayList; import java.util.Arrays; import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLEngineResult; import javax.net.ssl.SSLException; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.provider.javax.crypto.JSSNativeTrustManager; import org.mozilla.jss.provider.javax.crypto.JSSTrustManager; import org.mozilla.jss.ssl.SSLCipher; import org.mozilla.jss.ssl.SSLVersion; import org.mozilla.jss.ssl.javax.JSSEngine; import org.mozilla.jss.ssl.javax.JSSEngineReferenceImpl; import org.mozilla.jss.ssl.javax.JSSParameters; public class TestSSLEngine { public static boolean debug = false; public static ByteBuffer empty = ByteBuffer.allocate(0); public static int bufferCount = 10; public static ByteBuffer[] readQueue; public static ByteBuffer[] writeQueue; public static ByteBuffer CMCs = ByteBuffer.wrap("Cooking MCs".getBytes()); public static ByteBuffer LargeCMCs; public static ByteBuffer LAPOB = ByteBuffer.wrap("like a pound of bacon.".getBytes()); public static ByteBuffer LargeLAPOB; public static ByteBuffer LargeReadBuffer; public static ByteBuffer LargeWriteBuffer; public static void initialize(String[] args) throws Exception { CryptoManager cm = CryptoManager.getInstance(); cm.setPasswordCallback(new FilePasswordCallback(args[1])); sizeBuffers(); } public static void testProvided() throws Exception { SSLContext ctx = SSLContext.getInstance("TLS", "Mozilla-JSS"); System.err.println(ctx.getProvider()); SSLEngine raw_eng = ctx.createSSLEngine(); assert(raw_eng instanceof JSSEngine); System.out.println("Testing basic assumptions..."); testBasics(ctx); System.out.println("Testing byte buffer semantics..."); testByteBufferSemantics(ctx); } public static void testBasics(SSLContext ctx) throws Exception { // Tests adapted from jdk11u test suite for compliance. SSLEngine ssle = ctx.createSSLEngine(); // Tests {get,set}EnabledCipherSuites() String[] suites = ssle.getSupportedCipherSuites(); assert suites.length >= 2; String secondSuite = suites[1]; String[] oneSuites = new String[]{ secondSuite }; ssle.setEnabledCipherSuites(oneSuites); suites = ssle.getEnabledCipherSuites(); assert suites.length == 1; assert suites[0].equals(secondSuite); // Tests {get,set}EnabledProtocols() String[] protocols = ssle.getSupportedProtocols(); // Fedora returns at least 2 supported protocols // in FIPS mode, but RHEL returns only 1. assert protocols.length >= 1; String firstProtocol = protocols[0]; String[] oneProtocols = new String[]{ firstProtocol }; ssle.setEnabledProtocols(oneProtocols); protocols = ssle.getEnabledProtocols(); assert protocols.length == 1; assert protocols[0].equals(firstProtocol); // Tests {get,set}UseClientMode ssle.setUseClientMode(true); assert ssle.getUseClientMode() == true; ssle.setUseClientMode(false); assert ssle.getUseClientMode() == false; // Tests {get,set}{Want,Need}ClientAuth. Note that want and // need are mutually exclusive in that they both can't be // true. ssle.setWantClientAuth(false); assert ssle.getWantClientAuth() == false; ssle.setWantClientAuth(true); assert ssle.getWantClientAuth() == true; ssle.setNeedClientAuth(true); assert ssle.getNeedClientAuth() == true; ssle.setNeedClientAuth(false); assert ssle.getNeedClientAuth() == false; ssle.setUseClientMode(true); try { ByteBuffer buf = ByteBuffer.allocate(1024); byte[] random_data = "HELLO HELLO".getBytes(); ByteBuffer random_buf = ByteBuffer.wrap(random_data); ssle.wrap(buf, buf); ssle.unwrap(random_buf, buf); assert false; } catch (SSLException e) { assert true; } } public static void testByteBufferSemantics(SSLContext ctx) throws Exception { // Tests adapted from jdk11u test suite for compliance. Unlike JDK, we // gracefully handle null buffers when possible. SSLEngine ssle = ctx.createSSLEngine(); ByteBuffer roBB = ByteBuffer.allocate(40).asReadOnlyBuffer(); ByteBuffer bb1K = ByteBuffer.allocate(1024); ByteBuffer bb2K = ByteBuffer.allocate(2048); ByteBuffer bb4K = ByteBuffer.allocate(5096); ByteBuffer bb8K = ByteBuffer.allocate(10192); ByteBuffer[] bufs = new ByteBuffer[]{ bb1K, bb2K, bb4K, bb8K }; try { ssle.unwrap(bb1K, bufs, 1, 5); assert false; } catch (IllegalArgumentException iae) { assert true; } try { ssle.unwrap(bb1K, bufs, -1, 5); assert false; } catch (IndexOutOfBoundsException iae) { assert true; } try { ssle.unwrap(bb1K, bufs, -3, 4); assert false; } catch (IndexOutOfBoundsException iae) { assert true; } } public static JSSParameters createParameters() throws Exception { JSSParameters params = new JSSParameters(); params.setHostname("localhost"); return params; } public static JSSParameters createParameters(String alias) throws Exception { JSSParameters params = new JSSParameters(); params.setAlias(alias); params.setHostname("localhost"); return params; } public static KeyManager[] getKMs() throws Exception { KeyManagerFactory kmf = KeyManagerFactory.getInstance("NssX509", "Mozilla-JSS"); return kmf.getKeyManagers(); } public static KeyManager[] getKSKMs() throws Exception { KeyStore ks = KeyStore.getInstance("PKCS11", "Mozilla-JSS"); ks.load(null, null); KeyManagerFactory kmf = KeyManagerFactory.getInstance("NssX509", "Mozilla-JSS"); kmf.init(ks, null); return kmf.getKeyManagers(); } public static TrustManager[] getTMs() throws Exception { TrustManagerFactory tmf = TrustManagerFactory.getInstance("NssX509"); TrustManager[] tms = tmf.getTrustManagers(); for (TrustManager tm : tms) { if (tm instanceof JSSTrustManager) { // JSS test suite doesn't enable extended key usages, so // configure the TrustManager to allow them. JSSTrustManager jtm = (JSSTrustManager) tm; jtm.configureAllowMissingExtendedKeyUsage(true); } } return tms; } public static void sizeBuffers() throws Exception { SSLContext ctx = SSLContext.getInstance("TLS", "Mozilla-JSS"); ctx.init(getKMs(), getTMs(), null); SSLEngine jss_dummy = ctx.createSSLEngine(); SSLContext jsse_context = SSLContext.getInstance("TLS", "SunJSSE"); jsse_context.init(getKMs(), getTMs(), null); SSLEngine jsse_dummy = jsse_context.createSSLEngine(); int buffer_size = Math.max( jss_dummy.getSession().getApplicationBufferSize(), jsse_dummy.getSession().getApplicationBufferSize() ); readQueue = new ByteBuffer[bufferCount]; writeQueue = new ByteBuffer[bufferCount]; for (int i = 0; i < bufferCount; i ++) { readQueue[i] = ByteBuffer.allocate(buffer_size); writeQueue[i] = ByteBuffer.allocate(buffer_size); } String clientMessage = "Cooking MCs"; for (int i = 1; i < 10; i++) { clientMessage += clientMessage; } LargeCMCs = ByteBuffer.wrap(clientMessage.getBytes()); String serverMessage = "like a pound of bacon."; for (int i = 1; i < 10; i++) { serverMessage += serverMessage; } LargeLAPOB = ByteBuffer.wrap(serverMessage.getBytes()); int large_size = 2 * Math.max( clientMessage.length(), serverMessage.length() ); LargeReadBuffer = ByteBuffer.allocate(large_size); LargeWriteBuffer = ByteBuffer.allocate(large_size); } public static void resetBuffers() throws Exception { for (int i = 0; i < bufferCount; i ++) { if (readQueue[i].remaining() != readQueue[i].capacity()) { readQueue[i].clear(); } if (writeQueue[i].remaining() != writeQueue[i].capacity()) { writeQueue[i].clear(); } } CMCs.position(0); LargeCMCs.position(0); LAPOB.position(0); LargeLAPOB.position(0); if (LargeReadBuffer.remaining() != LargeReadBuffer.capacity()) { LargeReadBuffer.clear(); } if (LargeWriteBuffer.remaining() != LargeWriteBuffer.capacity()) { LargeWriteBuffer.clear(); } } public static void testHandshake(SSLEngine client_eng, SSLEngine server_eng, boolean allowFirst) throws Exception { // Ensure we exit in case of a bug... :-) int counter = 0; int max_steps = 20; boolean client_done = false; boolean server_done = false; client_eng.beginHandshake(); server_eng.beginHandshake(); ArrayList c2s_buffers = new ArrayList(); ArrayList s2c_buffers = new ArrayList(); // We're allocating buffers from the server's perspective. Client's // wrap buffer goes into a buffer from the readQueue, which gets // unwrapped ("read") by the server. Server's unwrap goes into a buffer // from the writeQueue, which gets wrapped ("written") by the server. resetBuffers(); int read_buffer = 0; int write_buffer = 0; for (counter = 0; counter < max_steps; counter++) { SSLEngineResult.HandshakeStatus client_state = client_eng.getHandshakeStatus(); SSLEngineResult.HandshakeStatus server_state = server_eng.getHandshakeStatus(); System.err.println("client_done=" + client_done + " | client_eng.getHandshakeStatus()=" + client_state + " | c2s_buffers.size=" + c2s_buffers.size()); System.err.println("server_done=" + server_done + " | server_eng.getHandshakeStatus()=" + server_state + " | s2c_buffers.size=" + s2c_buffers.size()); System.err.println("\n\n=====BEGIN CLIENT====="); if (!client_done && client_state == SSLEngineResult.HandshakeStatus.NEED_WRAP) { ByteBuffer src = empty; ByteBuffer dst = readQueue[read_buffer]; read_buffer = (read_buffer + 1) % bufferCount; int consumed = src.position(); SSLEngineResult r = client_eng.wrap(src, dst); if (r.getStatus() != SSLEngineResult.Status.OK) { throw new RuntimeException("Unknown result from client_eng.wrap(): " + r.getStatus()); } consumed = src.position() - consumed; dst.flip(); assert r.bytesConsumed() == consumed; assert r.bytesProduced() == dst.remaining(); if (dst.hasRemaining()) { // Since we flipped our buffer, we can use hasRemaining() // to check if there's data we should unwrap on the client // side. There is, so add it to the candidates. c2s_buffers.add(dst); } else { dst.clear(); read_buffer = (read_buffer + read_buffer - 1) % bufferCount; } } else if (!client_done && client_state == SSLEngineResult.HandshakeStatus.NEED_UNWRAP) { while (s2c_buffers.size() > 0) { ByteBuffer src = s2c_buffers.remove(0); ByteBuffer dst = writeQueue[write_buffer]; // Borrowing a buffer temporarily and then clearing it // means we don't need to increment our counter. int consumed = src.position(); SSLEngineResult r = client_eng.unwrap(src, dst); if (r.getStatus() != SSLEngineResult.Status.OK) { throw new RuntimeException("Unknown result from client_eng.unwrap(): " + r.getStatus()); } consumed = src.position() - consumed; dst.flip(); assert r.bytesConsumed() == consumed; assert r.bytesProduced() == dst.remaining(); assert !dst.hasRemaining(); dst.clear(); if (src.hasRemaining()) { // Since we have bytes left after reading it, put it // back on the front of the stack. s2c_buffers.add(0, src); // After only partially reading a buffer, it is // unlikely that we'll be able to continue, so break. break; } else { // Reset our buffer so when it gets reused it'll have // space free and no old contents. src.clear(); if (r.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NEED_UNWRAP) { break; } } } } else if ((counter > 1 || allowFirst) && !client_done && (client_state == SSLEngineResult.HandshakeStatus.FINISHED || client_state == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING)) { System.err.println("Client: " + server_eng.getHandshakeStatus()); client_done = true; } else if (!client_done && client_state == SSLEngineResult.HandshakeStatus.NEED_TASK) { /* Per SSLEngineSimpleDemo from Oracle. */ Runnable runnable; while ((runnable = client_eng.getDelegatedTask()) != null) { System.err.println("Client: running delegated task"); runnable.run(); } client_state = client_eng.getHandshakeStatus(); assert(client_state != SSLEngineResult.HandshakeStatus.NEED_TASK); } else if (!client_done) { throw new RuntimeException("Unknown status for client_eng: " + client_state); } else if (client_done && s2c_buffers.size() > 0) { System.err.println("Client: processing remaining buffers."); while (s2c_buffers.size() > 0) { ByteBuffer src = s2c_buffers.remove(0); ByteBuffer dst = writeQueue[write_buffer]; // Borrowing a buffer temporarily and then clearing it // means we don't need to increment our counter. int consumed = src.position(); SSLEngineResult r = client_eng.unwrap(src, dst); if (r.getStatus() != SSLEngineResult.Status.OK) { throw new RuntimeException("Unknown result from client_eng.unwrap(): " + r.getStatus()); } consumed = src.position() - consumed; dst.flip(); assert r.bytesConsumed() == consumed; assert r.bytesProduced() == dst.remaining(); assert !dst.hasRemaining(); dst.clear(); if (src.hasRemaining()) { // Since we have bytes left after reading it, put it // back on the front of the stack. s2c_buffers.add(0, src); // After only partially reading a buffer, it is // unlikely that we'll be able to continue, so break. break; } else { src.clear(); if (r.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NEED_UNWRAP) { break; } } } } System.err.println("=====END CLIENT=====\n\n"); System.err.println("\n\n=====BEGIN SERVER====="); if (!server_done && server_state == SSLEngineResult.HandshakeStatus.NEED_WRAP) { ByteBuffer src = empty; ByteBuffer dst = writeQueue[write_buffer]; write_buffer = (write_buffer + 1) % bufferCount; int consumed = src.position(); SSLEngineResult r = server_eng.wrap(src, dst); if (r.getStatus() != SSLEngineResult.Status.OK) { throw new RuntimeException("Unknown result from server_eng.wrap(): " + r.getStatus()); } consumed = src.position() - consumed; dst.flip(); assert r.bytesConsumed() == consumed; assert r.bytesProduced() == dst.remaining(); if (dst.hasRemaining()) { // Since we flipped our buffer, we can use hasRemaining() // to check if there's data we should unwrap on the client // side. There is, so add it to the candidates. s2c_buffers.add(dst); } else { dst.clear(); write_buffer = (write_buffer + write_buffer - 1) % bufferCount; } } else if (!server_done && server_state == SSLEngineResult.HandshakeStatus.NEED_UNWRAP) { while (c2s_buffers.size() > 0) { ByteBuffer src = c2s_buffers.remove(0); ByteBuffer dst = readQueue[read_buffer]; // Borrowing a buffer temporarily and then clearing it // means we don't need to increment our counter. int consumed = src.position(); SSLEngineResult r = server_eng.unwrap(src, dst); if (r.getStatus() != SSLEngineResult.Status.OK) { throw new RuntimeException("Unknown result from server_eng.unwrap(): " + r.getStatus()); } consumed = src.position() - consumed; dst.flip(); assert r.bytesConsumed() == consumed; assert r.bytesProduced() == dst.remaining(); assert !dst.hasRemaining(); dst.clear(); if (src.hasRemaining()) { // Since we have bytes left after reading it, put it // back on the front of the stack. c2s_buffers.add(0, src); // After only partially reading a buffer, it is // unlikely that we'll be able to continue, so break. break; } else { src.clear(); if (r.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NEED_UNWRAP) { break; } } } } else if ((counter > 1 || allowFirst) && !server_done && (server_state == SSLEngineResult.HandshakeStatus.FINISHED || server_state == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING)) { System.err.println("Server: " + server_eng.getHandshakeStatus()); server_done = true; } else if (!server_done && server_state == SSLEngineResult.HandshakeStatus.NEED_TASK) { /* Per SSLEngineSimpleDemo from Oracle. */ Runnable runnable; while ((runnable = server_eng.getDelegatedTask()) != null) { System.err.println("Server: running delegated task"); runnable.run(); } server_state = client_eng.getHandshakeStatus(); assert(server_state != SSLEngineResult.HandshakeStatus.NEED_TASK); } else if (!server_done) { throw new RuntimeException("Unknown status for server handshake status: " + server_state); } else if (server_done && c2s_buffers.size() > 0) { System.err.println("Server: processing remaining buffers."); while (c2s_buffers.size() > 0) { ByteBuffer src = c2s_buffers.remove(0); ByteBuffer dst = readQueue[read_buffer]; // Borrowing a buffer temporarily and then clearing it // means we don't need to increment our counter. int consumed = src.position(); SSLEngineResult r = server_eng.unwrap(src, dst); if (r.getStatus() != SSLEngineResult.Status.OK) { throw new RuntimeException("Unknown result from server_eng.unwrap(): " + r.getStatus()); } consumed = src.position() - consumed; dst.flip(); assert r.bytesConsumed() == consumed; assert r.bytesProduced() == dst.remaining(); assert !dst.hasRemaining(); dst.clear(); if (src.hasRemaining()) { // Since we have bytes left after reading it, put it // back on the front of the stack. c2s_buffers.add(0, src); // After only partially reading a buffer, it is // unlikely that we'll be able to continue, so break. break; } else { src.clear(); if (r.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.NEED_UNWRAP) { break; } } } } System.err.println("=====END SERVER=====\n\n"); if (client_done && server_done) { assert(s2c_buffers.size() == 0); assert(c2s_buffers.size() == 0); break; } } if (counter == max_steps) { throw new RuntimeException("Unable to complete a handshake in " + max_steps + " steps; assuming we were stuck in an infinite loop: c2s_buffers.size=" + c2s_buffers.size() + " s2c_buffers.size=" + s2c_buffers.size()); } SSLSession c_session = client_eng.getSession(); SSLSession s_session = server_eng.getSession(); assert(c_session.getCipherSuite() == s_session.getCipherSuite()); assert(c_session.getProtocol() == s_session.getProtocol()); if (server_eng.getNeedClientAuth()) { assert(s_session.getPeerCertificates() != null); } } public static void sendTestData(SSLEngine send, SSLEngine recv, ByteBuffer mesg, ByteBuffer inter, ByteBuffer dest) throws Exception { int start_pos = mesg.position(); int mesg_size = mesg.remaining(); int counter = 0; int max_counter = 10; SSLEngineResult r; for (counter = 0; counter < max_counter; counter++) { int consumed = mesg.position(); int produced = inter.position(); r = send.wrap(mesg, inter); consumed = mesg.position() - consumed; produced = inter.position() - produced; assert r.bytesConsumed() == consumed; assert r.bytesProduced() == produced; inter.flip(); System.err.println("Bytes of plaintext message: " + mesg_size); if (r.getStatus() != SSLEngineResult.Status.OK) { throw new RuntimeException("Unknown result from send.wrap(): " + r.getStatus()); } else if (mesg.hasRemaining()) { // Need to be called again to add more data. inter.flip(); continue; } else if (inter.hasRemaining()) { break; } } if (counter == max_counter) { throw new RuntimeException("Reasonably expected to get encrypted data during wrap."); } System.err.println("Bytes of ciphertext message: " + inter.remaining()); assert(inter.remaining() >= mesg_size); assert(dest.remaining() > inter.remaining()); for (counter = 0; counter < max_counter; counter++) { int consumed = inter.position(); int produced = dest.position(); r = recv.unwrap(inter, dest); consumed = inter.position() - consumed; produced = dest.position() - produced; assert r.bytesConsumed() == consumed; assert r.bytesProduced() == produced; dest.flip(); if (r.getStatus() != SSLEngineResult.Status.OK) { throw new RuntimeException("Unknown result from send.wrap(): " + r.getStatus()); } else if (!dest.hasRemaining()) { throw new RuntimeException("Reasonably expected to get decrypted data during unwrap. Have: " + dest.remaining()); } else if (dest.remaining() < mesg_size) { // Flip it back so we can append more data again. System.err.println("Expecting to get " + (mesg_size - dest.remaining()) + " more bytes... Calling unwrap again."); dest.flip(); continue; } else if (dest.remaining() >= mesg_size) { break; } } if (counter == max_counter) { throw new RuntimeException("Reasonably expected to get all decrypted data during unwrap but only got " + dest.remaining()); } System.err.println("Bytes of decrypted message: " + dest.remaining()); mesg.position(start_pos); byte[] orig = new byte[mesg.remaining()]; byte[] copy = new byte[dest.remaining()]; mesg.get(orig); dest.get(copy); if (!Arrays.equals(orig, copy)) { throw new RuntimeException("Expected data received to equal that sent!"); } } public static void testPostHandshakeTransfer(SSLEngine client_eng, SSLEngine server_eng) throws Exception { assert(client_eng.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING); assert(server_eng.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING); System.err.println("Testing post-handshake transfer..."); resetBuffers(); ByteBuffer client_msg = CMCs; ByteBuffer c2s_buffer = readQueue[0]; ByteBuffer server_unwrap = writeQueue[0]; sendTestData(client_eng, server_eng, client_msg, c2s_buffer, server_unwrap); ByteBuffer server_msg = LAPOB; ByteBuffer s2c_buffer = writeQueue[1]; ByteBuffer client_unwrap = readQueue[1]; sendTestData(server_eng, client_eng, server_msg, s2c_buffer, client_unwrap); client_msg = LargeCMCs; c2s_buffer = LargeWriteBuffer; server_unwrap = LargeReadBuffer; sendTestData(client_eng, server_eng, client_msg, c2s_buffer, server_unwrap); LargeReadBuffer.clear(); LargeWriteBuffer.clear(); server_msg = LargeLAPOB; s2c_buffer = LargeWriteBuffer; client_unwrap = LargeReadBuffer; sendTestData(server_eng, client_eng, server_msg, s2c_buffer, client_unwrap); System.err.println("Done testing post-handshake transfer! Success!"); } public static void sendCloseData(SSLEngine send, SSLEngine recv) throws Exception { int counter = 0; int max_tries = 20; resetBuffers(); ByteBuffer src = readQueue[0]; ByteBuffer transfer = writeQueue[0]; ByteBuffer read = readQueue[1]; System.out.println(src.capacity() + "/" + src.remaining() + "@" + src.position()); System.out.println(transfer.capacity() + "/" + transfer.remaining() + "@" + transfer.position()); System.out.println(read.capacity() + "/" + read.remaining() + "@" + read.position()); SSLEngineResult r = null; for (counter = 0; counter < max_tries; counter++) { r = send.wrap(src, transfer); transfer.flip(); if (r.getStatus() != SSLEngineResult.Status.OK && r.getStatus() != SSLEngineResult.Status.CLOSED) { throw new RuntimeException("Unknown result from send.wrap(): " + r.getStatus()); } else if (transfer.hasRemaining()) { break; } else { transfer.flip(); } } if (counter == max_tries) { throw new RuntimeException("Reasonably expected to send CLOSE_NOTIFY alert to other party."); } r = recv.unwrap(transfer, read); read.flip(); if (r.getStatus() != SSLEngineResult.Status.OK && r.getStatus() != SSLEngineResult.Status.CLOSED) { throw new RuntimeException("Unknown result from recv.unwrap(): " + r.getStatus()); } else if (read.hasRemaining()) { throw new RuntimeException("Expected not to recieve any data but got " + read.remaining() + " bytes during unwrap."); } } public static void testClose(SSLEngine client_eng, SSLEngine server_eng) throws Exception { assert(client_eng.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING || client_eng.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.FINISHED); assert(server_eng.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING || server_eng.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.FINISHED); if (client_eng instanceof JSSEngine) { assert(((JSSEngine) client_eng).getStatus().on >= 1); } if (server_eng instanceof JSSEngine) { assert(((JSSEngine) server_eng).getStatus().on >= 1); } assert(client_eng.isInboundDone() == false); assert(client_eng.isOutboundDone() == false); assert(server_eng.isInboundDone() == false); assert(server_eng.isOutboundDone() == false); System.err.println("Testing client close..."); client_eng.closeOutbound(); sendCloseData(client_eng, server_eng); assert(client_eng.isOutboundDone() == true); assert(server_eng.isInboundDone() == true); assert(server_eng.isOutboundDone() == false); assert(client_eng.isInboundDone() == false); System.err.println("Testing server close..."); server_eng.closeOutbound(); sendCloseData(server_eng, client_eng); // Everything should be done now... assert(server_eng.isOutboundDone() == true); assert(client_eng.isInboundDone() == true); System.err.println("Passed close test!"); } public static void testBasicHandshake(SSLEngine client_eng, SSLEngine server_eng, boolean allowFirst) throws Exception { testHandshake(client_eng, server_eng, allowFirst); testPostHandshakeTransfer(client_eng, server_eng); testClose(client_eng, server_eng); } public static void testInitialHandshake(SSLEngine client_eng, SSLEngine server_eng) throws Exception { testHandshake(client_eng, server_eng, false); testPostHandshakeTransfer(client_eng, server_eng); } public static void configureSSLEngine(SSLEngine eng, String protocol, String cipher_suite) throws Exception { eng.setEnabledProtocols(new String[] { protocol }); eng.setEnabledCipherSuites(new String[] { cipher_suite }); } public static boolean skipProtocolCipherSuite(String protocol, String cipher_suite, String client_alias, String server_alias) { SSLVersion v = SSLVersion.findByAlias(protocol); SSLCipher cs = SSLCipher.valueOf(cipher_suite); boolean works_with_version = cs.supportsTLSVersion(v); boolean is_rsa = client_alias.contains("RSA") && cs.requiresRSACert(); boolean is_ecdsa = client_alias.contains("ECDSA") && cs.requiresECDSACert(); boolean supported = cs.isSupported(); boolean null_cipher = cipher_suite.contains("NULL"); boolean right_cert_type = is_rsa || is_ecdsa; // The JSS test suite currently doesn't generate certificates // compatible with ECDH_RSA cipher suites. boolean is_ecdh_rsa = cipher_suite.contains("ECDH_RSA"); return (!works_with_version || !supported || !right_cert_type || null_cipher || is_ecdh_rsa); } public static void testAllHandshakes(SSLContext ctx, String client_alias, String server_alias, boolean client_auth) throws Exception { SSLEngine dummy = ctx.createSSLEngine(); assert(dummy != null); for (String protocol : dummy.getSupportedProtocols()) { for (String cipher_suite : dummy.getSupportedCipherSuites()) { if (skipProtocolCipherSuite(protocol, cipher_suite, client_alias, server_alias)) { continue; } System.err.println("Testing: " + protocol + " with " + cipher_suite); String context = protocol + "/" + cipher_suite; JSSEngine client_eng = (JSSEngine) ctx.createSSLEngine(); client_eng.setSSLParameters(createParameters(client_alias)); client_eng.setUseClientMode(true); if (client_eng instanceof JSSEngineReferenceImpl) { ((JSSEngineReferenceImpl) client_eng).setName("JSS Client " + context); } JSSEngine server_eng = (JSSEngine) ctx.createSSLEngine(); server_eng.setSSLParameters(createParameters(server_alias)); server_eng.setUseClientMode(false); if (server_eng instanceof JSSEngineReferenceImpl) { ((JSSEngineReferenceImpl) server_eng).setName("JSS Server " + context); if (debug) { ((JSSEngineReferenceImpl) server_eng).enableSafeDebugLogging(7377); } } if (client_auth) { server_eng.setNeedClientAuth(true); } configureSSLEngine(client_eng, protocol, cipher_suite); configureSSLEngine(server_eng, protocol, cipher_suite); try { testBasicHandshake(client_eng, server_eng, false); } catch (Exception e) { client_eng.cleanup(); server_eng.cleanup(); throw e; } } } } public static void testJSSEToJSSHandshakes(SSLContext jss_context, String server_alias) throws Exception { // We set this up as a JSS Server with JSSE client, forgoing client // authentication. Begin by setting up the JSSE context, complete with // supported protocols. SSLContext jsse_context = SSLContext.getInstance("TLS", "SunJSSE"); jsse_context.init(getKMs(), getTMs(), null); SSLEngine jsse_dummy = jsse_context.createSSLEngine(); String[] jsse_protocols = jsse_dummy.getSupportedProtocols(); Arrays.sort(jsse_protocols); String[] jsse_suites = jsse_dummy.getSupportedCipherSuites(); Arrays.sort(jsse_suites); SSLEngine dummy = jss_context.createSSLEngine(); for (String protocol : dummy.getSupportedProtocols()) { for (String cipher_suite : dummy.getSupportedCipherSuites()) { if (skipProtocolCipherSuite(protocol, cipher_suite, "", server_alias)) { continue; } if (Arrays.binarySearch(jsse_protocols, protocol) < 0) { System.err.println("JSSE doesn't support protocol: " + protocol); continue; } if (Arrays.binarySearch(jsse_suites, cipher_suite) < 0) { System.err.println("JSSE doesn't support this cipher suite: " + cipher_suite); continue; } System.err.println("Testing JSSE client with JSS server: " + protocol + " with " + cipher_suite); SSLEngine client_eng = jsse_context.createSSLEngine(); client_eng.setSSLParameters(createParameters()); client_eng.setUseClientMode(true); JSSEngine server_eng = (JSSEngine) jss_context.createSSLEngine(); server_eng.setSSLParameters(createParameters(server_alias)); server_eng.setUseClientMode(false); if (server_eng instanceof JSSEngineReferenceImpl) { if (debug) { ((JSSEngineReferenceImpl) server_eng).enableSafeDebugLogging(7374); } } configureSSLEngine(client_eng, protocol, cipher_suite); configureSSLEngine(server_eng, protocol, cipher_suite); try { testBasicHandshake(client_eng, server_eng, false); } catch (Exception e) { server_eng.cleanup(); throw e; } } } } public static void testPostHandshakeAuth(SSLContext ctx, String client_alias, String server_alias) throws Exception { SSLEngine dummy = ctx.createSSLEngine(); assert(dummy != null); for (String protocol : dummy.getSupportedProtocols()) { if (protocol != "TLSv1.2" && protocol != "TLSv1.3") { continue; } for (String cipher_suite : dummy.getSupportedCipherSuites()) { if (skipProtocolCipherSuite(protocol, cipher_suite, client_alias, server_alias)) { continue; } System.err.println("Testing: " + protocol + " with " + cipher_suite); String context = protocol + "/" + cipher_suite; JSSEngine client_eng = (JSSEngine) ctx.createSSLEngine(); client_eng.setSSLParameters(createParameters(client_alias)); client_eng.setUseClientMode(true); if (client_eng instanceof JSSEngineReferenceImpl) { ((JSSEngineReferenceImpl) client_eng).setName("JSS Client " + context); } JSSEngine server_eng = (JSSEngine) ctx.createSSLEngine(); server_eng.setSSLParameters(createParameters(server_alias)); server_eng.setUseClientMode(false); if (server_eng instanceof JSSEngineReferenceImpl) { ((JSSEngineReferenceImpl) server_eng).setName("JSS Server " + context); if (debug) { ((JSSEngineReferenceImpl) server_eng).enableSafeDebugLogging(7377); } } configureSSLEngine(client_eng, protocol, cipher_suite); configureSSLEngine(server_eng, protocol, cipher_suite); try { System.err.println("Starting initial handshake"); testInitialHandshake(client_eng, server_eng); // Require client auth and re-handshake server_eng.setWantClientAuth(true); server_eng.setNeedClientAuth(true); System.err.println("Starting second handshake"); testBasicHandshake(client_eng, server_eng, true); } catch (Exception e) { client_eng.cleanup(); server_eng.cleanup(); throw e; } } } } public static void testBasicClientServer(String[] args) throws Exception { SSLContext ctx = SSLContext.getInstance("TLS", "Mozilla-JSS"); ctx.init(getKMs(), getTMs(), null); String client_alias = args[2]; String server_alias = args[3]; testAllHandshakes(ctx, client_alias, server_alias, false); testAllHandshakes(ctx, client_alias, server_alias, true); testJSSEToJSSHandshakes(ctx, server_alias); } public static void testNativeClientServer(String[] args) throws Exception { SSLContext ctx = SSLContext.getInstance("TLS", "Mozilla-JSS"); ctx.init(getKSKMs(), new TrustManager[] { new JSSNativeTrustManager() }, null); String client_alias = args[2]; String server_alias = args[3]; testAllHandshakes(ctx, client_alias, server_alias, false); testAllHandshakes(ctx, client_alias, server_alias, true); testPostHandshakeAuth(ctx, client_alias, server_alias); testJSSEToJSSHandshakes(ctx, server_alias); } public static void main(String[] args) throws Exception { // Args: // - nssdb // - nssdb password // - client cert // - server cert System.out.println("Initializing CryptoManager..."); initialize(args); if (org.mozilla.jss.JSSProvider.ENABLE_JSSENGINE == false) { return; } assert(SSLVersion.TLS_1_2.matchesAlias("TLSv1.2")); System.out.println("Testing provided instance..."); testProvided(); System.out.println("Testing basic handshake with TMs from provider..."); testBasicClientServer(args); System.out.println("Testing basic handshake with native TM..."); testNativeClientServer(args); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/UTF8ConverterTest.java000066400000000000000000000040421412550063600253240ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.io.ByteArrayOutputStream; import java.io.OutputStreamWriter; import org.apache.commons.lang3.RandomStringUtils; import org.mozilla.jss.util.UTF8Converter; public class UTF8ConverterTest { public UTF8ConverterTest() throws Exception { } public void testUnicodeToUTF8() throws Exception { // Verify UnicodeToUTF8 by comparing its output // to that of the standard Java conversion routines. String input = RandomStringUtils.random(10); char[] unicode = input.toCharArray(); System.out.print("Input:"); for (int c : unicode) { System.out.print(String.format(" %04x", c)); } System.out.println(); byte[] utf8 = UTF8Converter.UnicodeToUTF8(unicode); System.out.print("Output 1:"); for (byte b : utf8) { System.out.print(String.format(" %02x", b)); } System.out.println(); ByteArrayOutputStream barray = new ByteArrayOutputStream(); OutputStreamWriter writer = new OutputStreamWriter(barray, "UTF8"); writer.write(unicode, 0, unicode.length); writer.close(); byte[] output = barray.toByteArray(); System.out.print("Output 2:"); for (byte b : output) { System.out.print(String.format(" %02x", b)); } System.out.println(); assert(utf8 != null); assert(utf8.length == output.length); for(int i=0; i " + " " + "\n"); System.out.println(" " + " " + "\n"); System.out.println("Note: and " + " are optional.\n But if used, " + "both Url/nickname must be specified."); } public static void main(String args[]) { try { VerifyCert vc = new VerifyCert(); if ( args.length < 3 ) { vc.usage(); return; } String dbdir = args[0]; String password = args[1]; String name = args[2]; String ResponderURL = null; String ResponderNickname = null; //if OCSPResponderURL than must have OCSPCertificateNickname if (args.length == 4 || args.length > 5) vc.usage(); else if (args.length == 5) { ResponderURL= args[3]; ResponderNickname = args[4]; } //initialize JSS InitializationValues vals = new InitializationValues(dbdir); //enable PKIX verify rather than the old NSS cert library, //to verify certificates. vals.PKIXVerify = true; // as a JSS test set the initialize for cooperate to true // One would set this to true if one configured NSS with // to use other PKCS11 modules. vals.cooperate = true; // configure OCSP vals.ocspCheckingEnabled = true; if (ResponderURL != null && ResponderNickname != null) { vals.ocspResponderCertNickname = ResponderNickname; vals.ocspResponderURL = ResponderURL; } CryptoManager cm = CryptoManager.getInstance(); PasswordCallback pwd = new Password(password.toCharArray()); cm.setPasswordCallback(pwd); try (FileInputStream fin = new FileInputStream(name)) { byte[] pkg = new byte[fin.available()]; fin.read(pkg); //display the cert vc.showCert(name); //validate the cert vc.validateDerCert(pkg, cm); } catch (java.io.FileNotFoundException e) { //assume name is a nickname of cert in the db vc.validateCertInDB(name, cm); } } catch ( Exception e ) { e.printStackTrace(); System.exit(1); } } public void validateDerCert(byte[] pkg, CryptoManager cm){ ArrayList usageList = new ArrayList<>(); try { Iterator list = CertUsage.getCertUsages(); CertUsage certUsage; while(list.hasNext()) { certUsage = list.next(); if ( !certUsage.equals(CertUsage.UserCertImport) && !certUsage.equals(CertUsage.ProtectedObjectSigner) && !certUsage.equals(CertUsage.AnyCA) ) { if (cm.isCertValid(pkg, true, certUsage) == true) { usageList.add(certUsage.toString()); } } } } catch (Exception e) { e.printStackTrace(); } if (usageList.isEmpty()) { System.out.println("The certificate is not valid."); } else { System.out.println("The certificate is valid for " + "the following usages:\n"); Iterator iterateUsage = usageList.iterator(); while (iterateUsage.hasNext()) { System.out.println(" " + iterateUsage.next()); } } } public void validateCertInDB(String nickname, CryptoManager cm){ ArrayList usageList = new ArrayList<>(); try { Iterator list = CertUsage.getCertUsages(); CertUsage certUsage; while(list.hasNext()) { certUsage = list.next(); if ( !certUsage.equals(CertUsage.UserCertImport) && !certUsage.equals(CertUsage.ProtectedObjectSigner) && !certUsage.equals(CertUsage.AnyCA) ) { if (cm.isCertValid(nickname, true, certUsage) == true) { usageList.add(certUsage.toString()); } } } } catch (Exception e) { e.printStackTrace(); } if (usageList.isEmpty()) { System.out.println("The certificate is not valid."); } else { System.out.println("The certificate is valid for the " + "following usages:\n"); Iterator iterateUsage = usageList.iterator(); while (iterateUsage.hasNext()) { System.out.println(" " + iterateUsage.next()); } } } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/X509CertTest.java000066400000000000000000000243361412550063600242010ustar00rootroot00000000000000/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package org.mozilla.jss.tests; import java.math.BigInteger; import java.security.KeyPair; import java.security.PrivateKey; import java.security.PublicKey; import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; import java.security.interfaces.RSAPublicKey; import java.util.Base64; import java.util.Calendar; import java.util.Date; import org.mozilla.jss.CertificateUsage; import org.mozilla.jss.CryptoManager; import org.mozilla.jss.crypto.CryptoToken; import org.mozilla.jss.crypto.KeyPairAlgorithm; import org.mozilla.jss.crypto.KeyPairGenerator; import org.mozilla.jss.crypto.X509Certificate; import org.mozilla.jss.netscape.security.util.BigInt; import org.mozilla.jss.netscape.security.util.DerValue; import org.mozilla.jss.netscape.security.x509.AlgorithmId; import org.mozilla.jss.netscape.security.x509.CertificateAlgorithmId; import org.mozilla.jss.netscape.security.x509.CertificateExtensions; import org.mozilla.jss.netscape.security.x509.CertificateIssuerName; import org.mozilla.jss.netscape.security.x509.CertificateSerialNumber; import org.mozilla.jss.netscape.security.x509.CertificateSubjectName; import org.mozilla.jss.netscape.security.x509.CertificateValidity; import org.mozilla.jss.netscape.security.x509.CertificateVersion; import org.mozilla.jss.netscape.security.x509.CertificateX509Key; import org.mozilla.jss.netscape.security.x509.X500Name; import org.mozilla.jss.netscape.security.x509.X509CertImpl; import org.mozilla.jss.netscape.security.x509.X509CertInfo; import org.mozilla.jss.netscape.security.x509.X509Key; import org.mozilla.jss.pkcs11.PK11ECPublicKey; import org.mozilla.jss.util.PasswordCallback; public class X509CertTest { public static String subjectDN = "CN = 8a99f98342b97d130142ba2cc30f07d3"; public static String issuerDN = "C = US, ST = North Carolina, O = Red Hat Inc., OU = Red Hat Network, CN = Red Hat Candlepin Authority, E = ca-support@redhat.com "; /* Just some sample code to exercise the new classes */ public static void main(String []args) throws Exception { if( args.length != 2 ) { System.out.println("Usage: X509CertTest "); return; } String dbdir = args[0]; String passwordfile = args[1]; Date notBefore = new Date(); Calendar cal = Calendar.getInstance(); cal.setTime(notBefore); cal.set(Calendar.YEAR, 2037); Date notAfter = cal.getTime(); //Generate ca keyPair CryptoManager cryptoManager = CryptoManager.getInstance(); CryptoToken token = cryptoManager.getInternalKeyStorageToken(); PasswordCallback cb = new FilePasswordCallback(passwordfile); token.login(cb); testEC(token, notBefore, notAfter); testRSA(token, notBefore, notAfter); testImport(); } public static void testEC(CryptoToken token, Date notBefore, Date notAfter) throws Exception { X509CertImpl certImpl = null; X509CertInfo certInfo = null; KeyPairGenerator gen = token.getKeyPairGenerator(KeyPairAlgorithm.EC); gen.initialize(gen.getCurveCodeByName("secp521r1")); KeyPair keypairCA = gen.genKeyPair(); testKeys(keypairCA); PublicKey pubCA = keypairCA.getPublic(); gen.initialize(gen.getCurveCodeByName("secp521r1")); KeyPair keypairUser = gen.genKeyPair(); testKeys(keypairUser); PublicKey pubUser = keypairUser.getPublic(); CertificateIssuerName issuernameObj = new CertificateIssuerName(new X500Name(issuerDN)); certInfo = createX509CertInfo(convertPublicKeyToX509Key(pubUser), BigInteger.valueOf(1),issuernameObj,subjectDN, notBefore, notAfter, "SHA256withEC"); certImpl = new X509CertImpl(certInfo); certImpl.sign(keypairCA.getPrivate(),"SHA256withEC"); String certOutput = certImpl.toString(); System.out.println("Test certificate output: \n" + certOutput); } public static void testRSA(CryptoToken token, Date notBefore, Date notAfter) throws Exception { X509CertImpl certImpl = null; X509CertInfo certInfo = null; KeyPairGenerator gen = token.getKeyPairGenerator(KeyPairAlgorithm.RSA); gen.initialize(4096); KeyPair keypairCA = gen.genKeyPair(); testKeys(keypairCA); PublicKey pubCA = keypairCA.getPublic(); gen.initialize(4096); KeyPair keypairUser = gen.genKeyPair(); testKeys(keypairUser); PublicKey pubUser = keypairUser.getPublic(); CertificateIssuerName issuernameObj = new CertificateIssuerName(new X500Name(issuerDN)); certInfo = createX509CertInfo(convertPublicKeyToX509Key(pubUser), BigInteger.valueOf(1),issuernameObj,subjectDN, notBefore, notAfter, "SHA256withRSA"); certImpl = new X509CertImpl(certInfo); certImpl.sign(keypairCA.getPrivate(),"SHA256withRSA"); String certOutput = certImpl.toString(); System.out.println("Test certificate output: \n" + certOutput); } public static void testKeys(KeyPair keypair) throws Exception { PublicKey pubKey = keypair.getPublic(); PrivateKey privKey = keypair.getPrivate(); if (pubKey instanceof ECPublicKey) { assert(privKey instanceof ECPrivateKey); ECPublicKey ecPub = (ECPublicKey)pubKey; ECPrivateKey ecPriv = (ECPrivateKey)privKey; // Two public functions we want to test on ECPublicKey: // 1. getW() -> ECPoint // 2. getParams() -> ECParameterSpec assert(ecPub.getW() != null); assert(ecPub.getW().getAffineX() != null); assert(ecPub.getW().getAffineY() != null); assert(ecPub.getParams() != null); assert(ecPriv.getParams() != null); // Since ECParameterSpec doesn't define a comparator, we have to // check each member individually. assert(ecPub.getParams().getCofactor() == ecPriv.getParams().getCofactor()); assert(ecPub.getParams().getCurve().equals(ecPriv.getParams().getCurve())); assert(ecPub.getParams().getGenerator().getAffineX().equals(ecPriv.getParams().getGenerator().getAffineX())); assert(ecPub.getParams().getGenerator().getAffineY().equals(ecPriv.getParams().getGenerator().getAffineY())); assert(ecPub.getParams().getOrder().equals(ecPriv.getParams().getOrder())); } } public static X509CertInfo createX509CertInfo(X509Key x509key, BigInteger serialno, CertificateIssuerName issuernameObj, String subjname, Date notBefore, Date notAfter, String alg) throws Exception { X509CertInfo info = new X509CertInfo(); info.set(X509CertInfo.VERSION, new CertificateVersion(CertificateVersion.V3)); info.set(X509CertInfo.SERIAL_NUMBER, new CertificateSerialNumber(serialno)); if (issuernameObj != null) { info.set(X509CertInfo.ISSUER, issuernameObj); } info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(new X500Name(subjname))); info.set(X509CertInfo.VALIDITY, new CertificateValidity(notBefore, notAfter)); info.set(X509CertInfo.ALGORITHM_ID, new CertificateAlgorithmId(AlgorithmId.get(alg))); info.set(X509CertInfo.KEY, new CertificateX509Key(x509key)); info.set(X509CertInfo.EXTENSIONS, new CertificateExtensions()); return info; } public static X509Key convertPublicKeyToX509Key(PublicKey pubk) throws Exception { X509Key xKey = null; if (pubk instanceof RSAPublicKey) { RSAPublicKey rsaKey = (RSAPublicKey) pubk; xKey = new org.mozilla.jss.netscape.security.provider.RSAPublicKey( new BigInt(rsaKey.getModulus()), new BigInt(rsaKey.getPublicExponent())); } else if (pubk instanceof PK11ECPublicKey) { byte encoded[] = pubk.getEncoded(); xKey = X509Key.parse(new DerValue(encoded)); } return xKey; } public static void testImport() throws Exception { CryptoManager cryptoManager = CryptoManager.getInstance(); byte[] cert = Base64.getDecoder().decode( "MIIDRjCCAi6gAwIBAgIJAMHiDXjnZ1J6MA0GCSqGSIb3DQEBCwUAMDgxEDAOBgNV" + "BAoMB0VYQU1QTEUxJDAiBgNVBAMMG1Jvb3QgQ0EgU2lnbmluZyBDZXJ0aWZpY2F0" + "ZTAeFw0xOTAzMDUxNzQzMjFaFw0yMDAzMDQxNzQzMjFaMDgxEDAOBgNVBAoMB0VY" + "QU1QTEUxJDAiBgNVBAMMG1Jvb3QgQ0EgU2lnbmluZyBDZXJ0aWZpY2F0ZTCCASIw" + "DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMDv7ovkD+JVEdlLncYDnhzbLOz2" + "c3D37fobufnHHNwNOwfLZj8WdBCzwGJv+XGF+D2JIcKyYwYPR+HOg+xClhuuVleE" + "gMVvgxM+HcpM4heyBD2QczNo1dfXQRBy2AXvRn8Byh+Q6zbN7VoNu8ZaMQOxZx9m" + "EAiDZ7WxHVrEp2a4QrI6I9gKY6SyEHRzVT48JElLFokwhkMpF8vhgtj0Xxr5EEIY" + "yCMOzvZLtpeyH8PUri3Cv/hX1RZKjWqKLSJSKirnZLhZoEEzXtsOmoeeZBeRiabi" + "dPLsxqPfWFx4+BC7t5Vw5FaIt2mPh+q6bjZipO4uWz/p4a9wpqakuzgNsYUCAwEA" + "AaNTMFEwHQYDVR0OBBYEFCvlfY9OzAVsYpJEoqr7QfguO9v5MB8GA1UdIwQYMBaA" + "FCvlfY9OzAVsYpJEoqr7QfguO9v5MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN" + "AQELBQADggEBAHB1lWjT6bP1jAkk6eTVwBU2pGoGoYMGV3fWQGOmWQP5T7+nHKkU" + "jNMRACoC2hFlypwX8qQ70V5O4U+qrnxDP3EaT1zPsOB0x4DIIrpFgudL9EqnSbJ0" + "kvSz3awwO8x/Nvx7TatCncmTw9c14eqek2puhcQWvxHzWkaDHd9WxPrZJFftbSsn" + "ZGK2A/ybDCnUA5BDeCSDb5gufTd8gbS4wS1NwYcbbrQyHnLJlFcIF4aLkbYuX1bn" + "cYp8pQv3pZ3C/ofA+yBJvPELTaHjDC40MTdjFFfMQTPZswBX2iimoGQ/ProBGg7+" + "rLg2uk5AHff3oo/V1X0SSzo3IpvHh0jhg9I=" ); X509Certificate ret = cryptoManager.importDERCert(cert, CertificateUsage.SSLCA, false, null); assert(ret != null); } } jss-5.0.0/src/test/java/org/mozilla/jss/tests/bbenvSample.sh000066400000000000000000000050161412550063600237770ustar00rootroot00000000000000#! /bin/bash ############################################################################## # Update java-1.8.0-openjdk to the latest and then do # sudo /usr/sbin/alternatives --config java and hit enter # # For example, to check/select your Java version on Linux: # # sudo /usr/sbin/alternatives --config java # # There is 1 program that provides 'java'. # # Selection Command # ----------------------------------------------- # *+ 1 java-1.8.0-openjdk.x86_64 (/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.111-3.b16.fc24.x86_64/jre/bin/java) # # Hit Enter to keep the current selection[+], or type selection number: # # You may have multiple entries (like on RHEl-7.x) or only one # This is for linux. On macOS you'll have something like this # JAVA_HOME_64=/Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Home # ############################################################################## # Each buildbot-slave requires a bbenv.sh file that defines # machine specific variables. This is an example file. HOST=$(hostname | cut -d. -f1) export HOST # if your machine's IP isn't registered in DNS, # you must set appropriate environment variables # that can be resolved locally. # For example, if localhost.localdomain works on your system, set: DOMSUF=localdomain export DOMSUF ARCH=$(uname -s) ulimit -c unlimited 2> /dev/null export NSPR_LOG_MODULES="pkix:1" #export JAVA_HOME_32= #export JAVA_HOME_64= #enable if you have PKITS data export PKITS_DATA=$HOME/pkits/ NSS_BUILD_TARGET="clean nss_build_all" JSS_BUILD_TARGET="clean all" MAKE=make AWK=awk PATCH=patch if [ "${ARCH}" = "SunOS" ]; then AWK=nawk PATCH=gpatch ARCH=SunOS/$(uname -p) fi if [ "${ARCH}" = "Linux" -a -f /etc/system-release ]; then #VERSION=`sed -e 's; release ;;' -e 's; (.*)$;;' -e 's;Red Hat Enterprise Linux Server;RHEL;' -e 's;Red Hat Enterprise Linux Workstation;RHEL;' /etc/system-release` VERSION=$(uname -r | awk -F"." '{ print $1 "." $2 }') ARCH=Linux/4.8 echo ${ARCH} fi PROCESSOR=$(uname -p) if [ "${PROCESSOR}" = "ppc64" ]; then ARCH="${ARCH}/ppc64" fi if [ "${PROCESSOR}" = "powerpc" ]; then ARCH="${ARCH}/ppc" fi PORT_64_DBG=8543 PORT_64_OPT=8544 PORT_32_DBG=8545 PORT_32_OPT=8546 if [ "${NSS_TESTS}" = "memleak" ]; then PORT_64_DBG=8547 PORT_64_OPT=8548 PORT_32_DBG=8549 PORT_32_OPT=8550 fi # change to suit your environent, refer to the instructions on how to do it # at the top of this file JAVA_HOME_64=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.111-3.b16.fc25.x86_64 export NSS_FORCE_FIPS=1 jss-5.0.0/src/test/java/org/mozilla/jss/tests/buffer_size_1.c000066400000000000000000000506211412550063600240760ustar00rootroot00000000000000#include "j_buffer.h" #include "assert.h" #include #include void test_jb(uint8_t* d) { j_buffer* b = jb_alloc(1); jb_free(b); b = jb_alloc(1); size_t r_o = 0; size_t w_o = 0; int i_r = 0; size_t s_r = 0; uint8_t* r_b = calloc(6, sizeof(uint8_t)); printf("Testing get+put\n"); // pc=0 gc=0 // pc=0 gc=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=0 gc=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=1 gc=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } // pc=1 gc=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=1 gc=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=2 gc=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } // pc=2 gc=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=2 gc=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } printf("Testing write+get\n"); // ws=0 gc=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 0); if (s_r != 0) { assert(s_r <= 0); w_o += s_r; } // ws=0 gc=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 0); if (s_r != 0) { assert(s_r <= 0); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=0 gc=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 0); if (s_r != 0) { assert(s_r <= 0); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=1 gc=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 1); if (s_r != 0) { assert(s_r <= 1); w_o += s_r; } // ws=1 gc=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 1); if (s_r != 0) { assert(s_r <= 1); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=1 gc=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 1); if (s_r != 0) { assert(s_r <= 1); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=2 gc=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 2); if (s_r != 0) { assert(s_r <= 2); w_o += s_r; } // ws=2 gc=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 2); if (s_r != 0) { assert(s_r <= 2); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=2 gc=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 2); if (s_r != 0) { assert(s_r <= 2); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } printf("Testing put+read\n"); // pc=0 rs=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_read(b, r_b, 0); if (s_r != 0) { assert(s_r <= 0); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=0 rs=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_read(b, r_b, 1); if (s_r != 0) { assert(s_r <= 1); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=0 rs=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_read(b, r_b, 2); if (s_r != 0) { assert(s_r <= 2); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=1 rs=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_read(b, r_b, 0); if (s_r != 0) { assert(s_r <= 0); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=1 rs=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_read(b, r_b, 1); if (s_r != 0) { assert(s_r <= 1); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=1 rs=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_read(b, r_b, 2); if (s_r != 0) { assert(s_r <= 2); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=2 rs=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_read(b, r_b, 0); if (s_r != 0) { assert(s_r <= 0); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=2 rs=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_read(b, r_b, 1); if (s_r != 0) { assert(s_r <= 1); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=2 rs=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_read(b, r_b, 2); if (s_r != 0) { assert(s_r <= 2); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } printf("Testing write+read\n"); // ws=0 rs=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 0); if (s_r != 0) { assert(s_r <= 0); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_read(b, r_b, 0); if (s_r != 0) { assert(s_r <= 0); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=0 rs=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 0); if (s_r != 0) { assert(s_r <= 0); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_read(b, r_b, 1); if (s_r != 0) { assert(s_r <= 1); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=0 rs=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 0); if (s_r != 0) { assert(s_r <= 0); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_read(b, r_b, 2); if (s_r != 0) { assert(s_r <= 2); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=1 rs=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 1); if (s_r != 0) { assert(s_r <= 1); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_read(b, r_b, 0); if (s_r != 0) { assert(s_r <= 0); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=1 rs=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 1); if (s_r != 0) { assert(s_r <= 1); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_read(b, r_b, 1); if (s_r != 0) { assert(s_r <= 1); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=1 rs=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 1); if (s_r != 0) { assert(s_r <= 1); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_read(b, r_b, 2); if (s_r != 0) { assert(s_r <= 2); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=2 rs=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 2); if (s_r != 0) { assert(s_r <= 2); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_read(b, r_b, 0); if (s_r != 0) { assert(s_r <= 0); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=2 rs=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 2); if (s_r != 0) { assert(s_r <= 2); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_read(b, r_b, 1); if (s_r != 0) { assert(s_r <= 1); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=2 rs=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 2); if (s_r != 0) { assert(s_r <= 2); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 1); assert(((w_o - r_o) < 1) == jb_can_write(b)); s_r = jb_read(b, r_b, 2); if (s_r != 0) { assert(s_r <= 2); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } } int main() { uint8_t* d = (uint8_t*)"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstu"; test_jb(d); return 0; } jss-5.0.0/src/test/java/org/mozilla/jss/tests/buffer_size_4.c000066400000000000000000004103671412550063600241100ustar00rootroot00000000000000#include "j_buffer.h" #include "assert.h" #include #include void test_jb(uint8_t* d) { j_buffer* b = jb_alloc(4); jb_free(b); b = jb_alloc(4); size_t r_o = 0; size_t w_o = 0; int i_r = 0; size_t s_r = 0; uint8_t* r_b = calloc(9, sizeof(uint8_t)); printf("Testing get+put\n"); // pc=0 gc=0 // pc=0 gc=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=0 gc=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=0 gc=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=0 gc=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=0 gc=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=1 gc=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } // pc=1 gc=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=1 gc=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=1 gc=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=1 gc=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=1 gc=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=2 gc=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } // pc=2 gc=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=2 gc=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=2 gc=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=2 gc=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=2 gc=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=3 gc=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } // pc=3 gc=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=3 gc=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=3 gc=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=3 gc=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=3 gc=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=4 gc=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } // pc=4 gc=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=4 gc=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=4 gc=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=4 gc=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=4 gc=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=5 gc=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } // pc=5 gc=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=5 gc=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=5 gc=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=5 gc=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // pc=5 gc=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } printf("Testing write+get\n"); // ws=0 gc=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 0); if (s_r != 0) { assert(s_r <= 0); w_o += s_r; } // ws=0 gc=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 0); if (s_r != 0) { assert(s_r <= 0); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=0 gc=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 0); if (s_r != 0) { assert(s_r <= 0); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=0 gc=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 0); if (s_r != 0) { assert(s_r <= 0); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=0 gc=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 0); if (s_r != 0) { assert(s_r <= 0); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=0 gc=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 0); if (s_r != 0) { assert(s_r <= 0); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=1 gc=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 1); if (s_r != 0) { assert(s_r <= 1); w_o += s_r; } // ws=1 gc=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 1); if (s_r != 0) { assert(s_r <= 1); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=1 gc=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 1); if (s_r != 0) { assert(s_r <= 1); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=1 gc=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 1); if (s_r != 0) { assert(s_r <= 1); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=1 gc=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 1); if (s_r != 0) { assert(s_r <= 1); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=1 gc=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 1); if (s_r != 0) { assert(s_r <= 1); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=2 gc=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 2); if (s_r != 0) { assert(s_r <= 2); w_o += s_r; } // ws=2 gc=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 2); if (s_r != 0) { assert(s_r <= 2); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=2 gc=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 2); if (s_r != 0) { assert(s_r <= 2); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=2 gc=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 2); if (s_r != 0) { assert(s_r <= 2); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=2 gc=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 2); if (s_r != 0) { assert(s_r <= 2); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=2 gc=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 2); if (s_r != 0) { assert(s_r <= 2); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=3 gc=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 3); if (s_r != 0) { assert(s_r <= 3); w_o += s_r; } // ws=3 gc=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 3); if (s_r != 0) { assert(s_r <= 3); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=3 gc=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 3); if (s_r != 0) { assert(s_r <= 3); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=3 gc=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 3); if (s_r != 0) { assert(s_r <= 3); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=3 gc=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 3); if (s_r != 0) { assert(s_r <= 3); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=3 gc=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 3); if (s_r != 0) { assert(s_r <= 3); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=4 gc=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 4); if (s_r != 0) { assert(s_r <= 4); w_o += s_r; } // ws=4 gc=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 4); if (s_r != 0) { assert(s_r <= 4); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=4 gc=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 4); if (s_r != 0) { assert(s_r <= 4); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=4 gc=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 4); if (s_r != 0) { assert(s_r <= 4); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=4 gc=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 4); if (s_r != 0) { assert(s_r <= 4); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=4 gc=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 4); if (s_r != 0) { assert(s_r <= 4); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=5 gc=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 5); if (s_r != 0) { assert(s_r <= 5); w_o += s_r; } // ws=5 gc=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 5); if (s_r != 0) { assert(s_r <= 5); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=5 gc=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 5); if (s_r != 0) { assert(s_r <= 5); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=5 gc=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 5); if (s_r != 0) { assert(s_r <= 5); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=5 gc=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 5); if (s_r != 0) { assert(s_r <= 5); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } // ws=5 gc=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 5); if (s_r != 0) { assert(s_r <= 5); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_get(b); if (i_r != EOF) { assert(((uint8_t)i_r) == ((uint8_t)d[r_o])); r_o += 1; } printf("Testing put+read\n"); // pc=0 rs=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 0); if (s_r != 0) { assert(s_r <= 0); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=0 rs=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 1); if (s_r != 0) { assert(s_r <= 1); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=0 rs=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 2); if (s_r != 0) { assert(s_r <= 2); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=0 rs=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 3); if (s_r != 0) { assert(s_r <= 3); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=0 rs=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 4); if (s_r != 0) { assert(s_r <= 4); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=0 rs=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 5); if (s_r != 0) { assert(s_r <= 5); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=1 rs=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 0); if (s_r != 0) { assert(s_r <= 0); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=1 rs=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 1); if (s_r != 0) { assert(s_r <= 1); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=1 rs=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 2); if (s_r != 0) { assert(s_r <= 2); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=1 rs=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 3); if (s_r != 0) { assert(s_r <= 3); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=1 rs=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 4); if (s_r != 0) { assert(s_r <= 4); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=1 rs=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 5); if (s_r != 0) { assert(s_r <= 5); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=2 rs=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 0); if (s_r != 0) { assert(s_r <= 0); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=2 rs=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 1); if (s_r != 0) { assert(s_r <= 1); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=2 rs=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 2); if (s_r != 0) { assert(s_r <= 2); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=2 rs=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 3); if (s_r != 0) { assert(s_r <= 3); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=2 rs=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 4); if (s_r != 0) { assert(s_r <= 4); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=2 rs=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 5); if (s_r != 0) { assert(s_r <= 5); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=3 rs=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 0); if (s_r != 0) { assert(s_r <= 0); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=3 rs=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 1); if (s_r != 0) { assert(s_r <= 1); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=3 rs=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 2); if (s_r != 0) { assert(s_r <= 2); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=3 rs=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 3); if (s_r != 0) { assert(s_r <= 3); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=3 rs=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 4); if (s_r != 0) { assert(s_r <= 4); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=3 rs=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 5); if (s_r != 0) { assert(s_r <= 5); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=4 rs=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 0); if (s_r != 0) { assert(s_r <= 0); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=4 rs=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 1); if (s_r != 0) { assert(s_r <= 1); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=4 rs=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 2); if (s_r != 0) { assert(s_r <= 2); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=4 rs=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 3); if (s_r != 0) { assert(s_r <= 3); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=4 rs=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 4); if (s_r != 0) { assert(s_r <= 4); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=4 rs=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 5); if (s_r != 0) { assert(s_r <= 5); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=5 rs=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 0); if (s_r != 0) { assert(s_r <= 0); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=5 rs=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 1); if (s_r != 0) { assert(s_r <= 1); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=5 rs=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 2); if (s_r != 0) { assert(s_r <= 2); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=5 rs=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 3); if (s_r != 0) { assert(s_r <= 3); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=5 rs=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 4); if (s_r != 0) { assert(s_r <= 4); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // pc=5 rs=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); i_r = jb_put(b, d[w_o]); if (i_r != EOF) { w_o += 1; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 5); if (s_r != 0) { assert(s_r <= 5); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } printf("Testing write+read\n"); // ws=0 rs=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 0); if (s_r != 0) { assert(s_r <= 0); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 0); if (s_r != 0) { assert(s_r <= 0); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=0 rs=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 0); if (s_r != 0) { assert(s_r <= 0); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 1); if (s_r != 0) { assert(s_r <= 1); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=0 rs=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 0); if (s_r != 0) { assert(s_r <= 0); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 2); if (s_r != 0) { assert(s_r <= 2); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=0 rs=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 0); if (s_r != 0) { assert(s_r <= 0); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 3); if (s_r != 0) { assert(s_r <= 3); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=0 rs=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 0); if (s_r != 0) { assert(s_r <= 0); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 4); if (s_r != 0) { assert(s_r <= 4); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=0 rs=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 0); if (s_r != 0) { assert(s_r <= 0); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 5); if (s_r != 0) { assert(s_r <= 5); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=1 rs=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 1); if (s_r != 0) { assert(s_r <= 1); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 0); if (s_r != 0) { assert(s_r <= 0); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=1 rs=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 1); if (s_r != 0) { assert(s_r <= 1); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 1); if (s_r != 0) { assert(s_r <= 1); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=1 rs=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 1); if (s_r != 0) { assert(s_r <= 1); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 2); if (s_r != 0) { assert(s_r <= 2); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=1 rs=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 1); if (s_r != 0) { assert(s_r <= 1); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 3); if (s_r != 0) { assert(s_r <= 3); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=1 rs=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 1); if (s_r != 0) { assert(s_r <= 1); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 4); if (s_r != 0) { assert(s_r <= 4); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=1 rs=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 1); if (s_r != 0) { assert(s_r <= 1); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 5); if (s_r != 0) { assert(s_r <= 5); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=2 rs=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 2); if (s_r != 0) { assert(s_r <= 2); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 0); if (s_r != 0) { assert(s_r <= 0); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=2 rs=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 2); if (s_r != 0) { assert(s_r <= 2); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 1); if (s_r != 0) { assert(s_r <= 1); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=2 rs=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 2); if (s_r != 0) { assert(s_r <= 2); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 2); if (s_r != 0) { assert(s_r <= 2); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=2 rs=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 2); if (s_r != 0) { assert(s_r <= 2); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 3); if (s_r != 0) { assert(s_r <= 3); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=2 rs=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 2); if (s_r != 0) { assert(s_r <= 2); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 4); if (s_r != 0) { assert(s_r <= 4); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=2 rs=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 2); if (s_r != 0) { assert(s_r <= 2); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 5); if (s_r != 0) { assert(s_r <= 5); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=3 rs=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 3); if (s_r != 0) { assert(s_r <= 3); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 0); if (s_r != 0) { assert(s_r <= 0); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=3 rs=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 3); if (s_r != 0) { assert(s_r <= 3); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 1); if (s_r != 0) { assert(s_r <= 1); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=3 rs=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 3); if (s_r != 0) { assert(s_r <= 3); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 2); if (s_r != 0) { assert(s_r <= 2); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=3 rs=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 3); if (s_r != 0) { assert(s_r <= 3); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 3); if (s_r != 0) { assert(s_r <= 3); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=3 rs=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 3); if (s_r != 0) { assert(s_r <= 3); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 4); if (s_r != 0) { assert(s_r <= 4); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=3 rs=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 3); if (s_r != 0) { assert(s_r <= 3); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 5); if (s_r != 0) { assert(s_r <= 5); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=4 rs=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 4); if (s_r != 0) { assert(s_r <= 4); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 0); if (s_r != 0) { assert(s_r <= 0); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=4 rs=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 4); if (s_r != 0) { assert(s_r <= 4); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 1); if (s_r != 0) { assert(s_r <= 1); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=4 rs=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 4); if (s_r != 0) { assert(s_r <= 4); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 2); if (s_r != 0) { assert(s_r <= 2); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=4 rs=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 4); if (s_r != 0) { assert(s_r <= 4); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 3); if (s_r != 0) { assert(s_r <= 3); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=4 rs=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 4); if (s_r != 0) { assert(s_r <= 4); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 4); if (s_r != 0) { assert(s_r <= 4); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=4 rs=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 4); if (s_r != 0) { assert(s_r <= 4); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 5); if (s_r != 0) { assert(s_r <= 5); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=5 rs=0 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 5); if (s_r != 0) { assert(s_r <= 5); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 0); if (s_r != 0) { assert(s_r <= 0); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=5 rs=1 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 5); if (s_r != 0) { assert(s_r <= 5); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 1); if (s_r != 0) { assert(s_r <= 1); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=5 rs=2 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 5); if (s_r != 0) { assert(s_r <= 5); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 2); if (s_r != 0) { assert(s_r <= 2); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=5 rs=3 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 5); if (s_r != 0) { assert(s_r <= 5); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 3); if (s_r != 0) { assert(s_r <= 3); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=5 rs=4 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 5); if (s_r != 0) { assert(s_r <= 5); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 4); if (s_r != 0) { assert(s_r <= 4); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } // ws=5 rs=5 assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_write(b, d + w_o, 5); if (s_r != 0) { assert(s_r <= 5); w_o += s_r; } assert(r_o <= w_o); assert((r_o < w_o) == jb_can_read(b)); assert((w_o - r_o) <= 4); assert(((w_o - r_o) < 4) == jb_can_write(b)); s_r = jb_read(b, r_b, 5); if (s_r != 0) { assert(s_r <= 5); for (size_t i = 0; i < s_r; i++) { assert(d[r_o] == r_b[i]); r_o += 1; } } } int main() { uint8_t* d = (uint8_t*)"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrs"; test_jb(d); return 0; } jss-5.0.0/src/test/java/org/mozilla/jss/tests/passwords000066400000000000000000000001251412550063600231510ustar00rootroot00000000000000Internal\ Key\ Storage\ Token=m1oZilla NSS\ FIPS\ 140-2\ User\ Private\ Key=m1oZilla jss-5.0.0/src/test/java/org/mozilla/jss/tests/runSample.sh000066400000000000000000000006621412550063600235110ustar00rootroot00000000000000#!/usr/bin/bash # NOTE: Read the notes at the top of bbenv.sh on how to set things up for # different systems # define a COMPILER_TAG to sync NSS and JSS 'OBJDIR_NAME' directory names export COMPILER_TAG=_gcc export NSPR_DS_INCLUDE=`pwd`/hg/nspr/lib/ds export RUN_BITS=64 export RUN_OPT=DBG export ENVVARS=`pwd`/bbenv.sh # --test-nss ./hg/nss/automation/buildbot-slave/build.sh --build-nss --build-jss --test-jss --nojsssign jss-5.0.0/src/test/java/org/mozilla/jss/tests/startJssSelfServ.sh000077500000000000000000000014431412550063600250330ustar00rootroot00000000000000#!/bin/sh # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ######################################################################## # # "Starting JSS JSS_SelfServServer..." # JSS_CLASSPATH=$1 TESTDIR=$2 HOSTNAME=$3 PORT=$4 shift 4 JAVA_BIN_AND_OPT=$@ if [ -z "$JAVA_BIN_AND_OPT" ] ; then JAVA_BIN_AND_OPT=${JAVA_HOME}/bin/java fi echo "${JAVA_BIN_AND_OPT} -classpath ${JSS_CLASSPATH} org.mozilla.jss.tests.JSS_SelfServServer ${TESTDIR} passwords ${HOSTNAME} false ${PORT} verboseoff &" ${JAVA_BIN_AND_OPT} -classpath ${JSS_CLASSPATH} org.mozilla.jss.tests.JSS_SelfServServer ${TESTDIR} passwords ${HOSTNAME} false ${PORT} verboseoff & jss-5.0.0/src/test/java/org/mozilla/jss/tests/startJssServ.sh000077500000000000000000000012141412550063600242150ustar00rootroot00000000000000#!/bin/sh # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ######################################################################## # # "Starting JSS JAA_SSLServer..." # JSS_CLASSPATH=$1 TESTDIR=$2 Port=$3 FipsMode=$4 shift 4 JAVA_BIN_AND_OPT=$@ if [ -z "$JAVA_BIN_AND_OPT" ] ; then JAVA_BIN_AND_OPT=${JAVA_HOME}/bin/java fi ${JAVA_BIN_AND_OPT} -classpath ${JSS_CLASSPATH} org.mozilla.jss.tests.JSS_SSLServer ${TESTDIR} passwords localhost JSSTestServerCert true ${Port} ${FipsMode} & jss-5.0.0/src/test/java/org/mozilla/jss/tests/startJsseServ.sh000077500000000000000000000023101412550063600243600ustar00rootroot00000000000000#!/bin/sh # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. ######################################################################## # # "Starting JSSE JSSE_SSLServer Test..." # JSS_CLASSPATH=$1 Port=$2 ClientAuth=$3 TestDir=$4 dbFile=$5 provider=$6 nssConfigFile=$7 nssPWFile=$8 shift 8 JAVA_BIN_AND_OPT=$@ if [ -z "$JAVA_BIN_AND_OPT" ] ; then JAVA_BIN_AND_OPT=${JAVA_HOME}/bin/java fi #echo "command" #echo "JSS_CLASSPATH=${JSS_CLASSPATH}" #echo "Port=${Port}" #echo "ClientAuth=${ClientAuth}" #echo "TestDir=${TestDir}" #echo "dbFile=${dbFile}" #echo "provider=${provider}" #echo "nssConfigFile=${nssConfigFile}" #echo "nssPWFile=${nssPWFile}" #echo "JAVA_BIN_AND_OPT=${JAVA_BIN_AND_OPT}" echo "${JAVA_BIN_AND_OPT} -classpath ${JSS_CLASSPATH} org.mozilla.jss.tests.JSSE_SSLServer ${Port} TLS ${ClientAuth} ${TestDir} ${dbFile} ${provider} ${nssConfigFile} ${nssPWFile}&" echo "command" ${JAVA_BIN_AND_OPT} -classpath ${JSS_CLASSPATH} org.mozilla.jss.tests.JSSE_SSLServer ${Port} TLS ${ClientAuth} ${TestDir} ${dbFile} ${provider} ${nssConfigFile} ${nssPWFile}& jss-5.0.0/src/test/java/org/mozilla/jss/tests/unix.sh000066400000000000000000000147221412550063600225300ustar00rootroot00000000000000# # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. #!/usr/bin/tcsh if ( `uname` == "AIX" ) then setenv LIBPATH ../../../../../dist/AIX4.2_DBG.OBJ/lib:/share/builds/components/jdk/1.1.6/AIX/lib/aix/native_threads echo Testing \"jssjava\" on `uname` `uname -v`.`uname -r` DBG platform . . . ../../../../../dist/AIX4.2_DBG.OBJ/bin/jssjava -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.6/AIX/lib/classes.zip org.mozilla.jss.crypto.PQGGen 512 echo Testing \"jssjava_g\" on `uname` `uname -v`.`uname -r` DBG platform . . . ../../../../../dist/AIX4.2_DBG.OBJ/bin/jssjava_g -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.6/AIX/lib/classes.zip org.mozilla.jss.crypto.PQGGen 512 setenv LIBPATH ../../../../../dist/AIX4.2_OPT.OBJ/lib:/share/builds/components/jdk/1.1.6/AIX/lib/aix/native_threads echo Testing \"jssjava\" on `uname` `uname -v`.`uname -r` OPT platform . . . ../../../../../dist/AIX4.2_OPT.OBJ/bin/jssjava -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.6/AIX/lib/classes.zip org.mozilla.jss.crypto.PQGGen 512 else if ( `uname` == "HP-UX" ) then setenv SHLIB_PATH ../../../../../dist/HP-UXB.11.00_DBG.OBJ/lib:/share/builds/components/jdk/1.1.5/HP-UX/lib/PA_RISC/native_threads echo Testing \"jssjava\" on `uname` `uname -r` DBG platform . . . ../../../../../dist/HP-UXB.11.00_DBG.OBJ/bin/jssjava -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.5/HP-UX/lib/classes.zip org.mozilla.jss.crypto.PQGGen 512 echo Testing \"jssjava_g\" on `uname` `uname -r` DBG platform . . . ../../../../../dist/HP-UXB.11.00_DBG.OBJ/bin/jssjava_g -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.5/HP-UX/lib/classes.zip org.mozilla.jss.crypto.PQGGen 512 setenv SHLIB_PATH ../../../../../dist/HP-UXB.11.00_OPT.OBJ/lib:/share/builds/components/jdk/1.1.5/HP-UX/lib/PA_RISC/native_threads echo Testing \"jssjava\" on `uname` `uname -r` OPT platform . . . ../../../../../dist/HP-UXB.11.00_OPT.OBJ/bin/jssjava -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.5/HP-UX/lib/classes.zip org.mozilla.jss.crypto.PQGGen 512 else if ( ( `uname` == "IRIX" ) || ( `uname` == "IRIX64" ) ) then setenv LD_LIBRARY_PATH ../../../../../dist/IRIX6.2_PTH_DBG.OBJ/lib:/share/builds/components/jdk/1.1.5/IRIX/lib32/sgi/native_threads echo Testing \"jssjava\" on `uname` `uname -r` DBG platform . . . ../../../../../dist/IRIX6.2_PTH_DBG.OBJ/bin/jssjava -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.5/IRIX/lib/rt.jar org.mozilla.jss.crypto.PQGGen 512 echo Testing \"jssjava_g\" on `uname` `uname -r` DBG platform . . . ../../../../../dist/IRIX6.2_PTH_DBG.OBJ/bin/jssjava_g -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.5/IRIX/lib/rt.jar org.mozilla.jss.crypto.PQGGen 512 setenv LD_LIBRARY_PATH ../../../../../dist/IRIX6.2_PTH_OPT.OBJ/lib:/share/builds/components/jdk/1.1.5/IRIX/lib32/sgi/native_threads echo Testing \"jssjava\" on `uname` `uname -r` OPT platform . . . ../../../../../dist/IRIX6.2_PTH_OPT.OBJ/bin/jssjava -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.5/IRIX/lib/rt.jar org.mozilla.jss.crypto.PQGGen 512 else if ( `uname` == "OSF1" ) then setenv LD_LIBRARY_PATH ../../../../../dist/OSF1V4.0D_DBG.OBJ/lib:/share/builds/components/jdk/1.1.6/OSF1/lib/alpha echo Testing \"jssjava\" on `uname` `uname -r`D DBG platform . . . ../../../../../dist/OSF1V4.0D_DBG.OBJ/bin/jssjava -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.5/OSF1/lib/classes.zip org.mozilla.jss.crypto.PQGGen 512 echo Testing \"jssjava_g\" on `uname` `uname -r`D DBG platform . . . ../../../../../dist/OSF1V4.0D_DBG.OBJ/bin/jssjava_g -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.5/OSF1/lib/classes.zip org.mozilla.jss.crypto.PQGGen 512 setenv LD_LIBRARY_PATH ../../../../../dist/OSF1V4.0D_OPT.OBJ/lib:/share/builds/components/jdk/1.1.6/OSF1/lib/alpha echo Testing \"jssjava\" on `uname` `uname -r`D OPT platform . . . ../../../../../dist/OSF1V4.0D_OPT.OBJ/bin/jssjava -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.5/OSF1/lib/classes.zip org.mozilla.jss.crypto.PQGGen 512 else if ( ( `uname` == "SunOS" ) && ( `uname -r` == "5.5.1" ) ) then setenv LD_LIBRARY_PATH ../../../../../dist/SunOS5.5.1_DBG.OBJ/lib:/share/builds/components/jdk/1.1.6/SunOS/lib/sparc/native_threads echo Testing \"jssjava\" on `uname` `uname -r` DBG platform . . . ../../../../../dist/SunOS5.5.1_DBG.OBJ/bin/jssjava -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.6/SunOS/lib/classes.zip org.mozilla.jss.crypto.PQGGen 512 echo Testing \"jssjava_g\" on `uname` `uname -r` DBG platform . . . ../../../../../dist/SunOS5.5.1_DBG.OBJ/bin/jssjava_g -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.6/SunOS/lib/classes.zip org.mozilla.jss.crypto.PQGGen 512 setenv LD_LIBRARY_PATH ../../../../../dist/SunOS5.5.1_OPT.OBJ/lib:/share/builds/components/jdk/1.1.6/SunOS/lib/sparc/native_threads echo Testing \"jssjava\" on `uname` `uname -r` OPT platform . . . ../../../../../dist/SunOS5.5.1_OPT.OBJ/bin/jssjava -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.6/SunOS/lib/classes.zip org.mozilla.jss.crypto.PQGGen 512 else if ( ( `uname` == "SunOS" ) && ( `uname -r` == "5.6" ) ) then setenv LD_LIBRARY_PATH ../../../../../dist/SunOS5.6_DBG.OBJ/lib:/share/builds/components/jdk/1.1.6/SunOS/lib/sparc/native_threads echo Testing \"jssjava\" on `uname` `uname -r` DBG platform . . . ../../../../../dist/SunOS5.6_DBG.OBJ/bin/jssjava -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.6/SunOS/lib/classes.zip org.mozilla.jss.crypto.PQGGen 512 echo Testing \"jssjava_g\" on `uname` `uname -r` DBG platform . . . ../../../../../dist/SunOS5.6_DBG.OBJ/bin/jssjava_g -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.6/SunOS/lib/classes.zip org.mozilla.jss.crypto.PQGGen 512 setenv LD_LIBRARY_PATH ../../../../../dist/SunOS5.6_OPT.OBJ/lib:/share/builds/components/jdk/1.1.6/SunOS/lib/sparc/native_threads echo Testing \"jssjava\" on `uname` `uname -r` OPT platform . . . ../../../../../dist/SunOS5.6_OPT.OBJ/bin/jssjava -classpath ../../../../../dist/classes:/share/builds/components/jdk/1.1.6/SunOS/lib/classes.zip org.mozilla.jss.crypto.PQGGen 512 endif jss-5.0.0/tests/000077500000000000000000000000001412550063600134575ustar00rootroot00000000000000jss-5.0.0/tests/bin/000077500000000000000000000000001412550063600142275ustar00rootroot00000000000000jss-5.0.0/tests/bin/ds-artifacts-save.sh000077500000000000000000000007611412550063600201120ustar00rootroot00000000000000#!/bin/bash CONTAINER=$1 INSTANCE=$2 if [ "$INSTANCE" == "" ] then INSTANCE=localhost fi ARTIFACTS=/tmp/artifacts/$CONTAINER mkdir -p $ARTIFACTS/etc mkdir -p $ARTIFACTS/var/log docker exec $CONTAINER ls -la /etc/dirsrv docker cp $CONTAINER:/etc/dirsrv $ARTIFACTS/etc docker exec $CONTAINER ls -la /var/log/dirsrv docker cp $CONTAINER:/var/log/dirsrv $ARTIFACTS/var/log docker exec $CONTAINER journalctl -u dirsrv@$INSTANCE.service > $ARTIFACTS/var/log/dirsrv/slapd-$INSTANCE/systemd.log jss-5.0.0/tests/bin/ds-create.sh000077500000000000000000000011321412550063600164320ustar00rootroot00000000000000#!/bin/bash -ex # This command needs to be executed as it pulls the machine name # dynamically. dscreate create-template ds.inf sed -i \ -e "s/;instance_name = .*/instance_name = localhost/g" \ -e "s/;root_password = .*/root_password = Secret.123/g" \ -e "s/;suffix = .*/suffix = dc=example,dc=com/g" \ -e "s/;self_sign_cert = .*/self_sign_cert = False/g" \ ds.inf dscreate from-file ds.inf ldapadd -h $HOSTNAME -x -D "cn=Directory Manager" -w Secret.123 << EOF dn: dc=example,dc=com objectClass: domain dc: example dn: dc=pki,dc=example,dc=com objectClass: domain dc: pki EOF jss-5.0.0/tests/bin/ds-remove.sh000077500000000000000000000000661412550063600164710ustar00rootroot00000000000000#!/bin/bash -ex dsctl slapd-localhost remove --do-it jss-5.0.0/tests/bin/init-workflow.sh000077500000000000000000000005651412550063600174070ustar00rootroot00000000000000#!/bin/bash -e if [ "$BASE64_MATRIX" == "" ] then MATRIX="{\"os\":[\"latest\"]}" else MATRIX=$(echo "$BASE64_MATRIX" | base64 -d) fi echo "MATRIX: $MATRIX" echo "::set-output name=matrix::$MATRIX" if [ "$BASE64_REPO" == "" ] then REPO="@pki/master" else REPO=$(echo "$BASE64_REPO" | base64 -d) fi echo "REPO: $REPO" echo "::set-output name=repo::$REPO" jss-5.0.0/tests/bin/pki-artifacts-save.sh000077500000000000000000000010561412550063600202650ustar00rootroot00000000000000#!/bin/bash CONTAINER=$1 INSTANCE=$2 if [ "$INSTANCE" == "" ] then INSTANCE=pki-tomcat fi ARTIFACTS=/tmp/artifacts/$CONTAINER mkdir -p $ARTIFACTS/etc/pki mkdir -p $ARTIFACTS/var/log docker exec $CONTAINER ls -la /etc/pki docker cp $CONTAINER:/etc/pki/pki.conf $ARTIFACTS/etc/pki docker cp $CONTAINER:/etc/pki/$INSTANCE $ARTIFACTS/etc/pki docker exec $CONTAINER ls -la /var/log/pki docker cp $CONTAINER:/var/log/pki $ARTIFACTS/var/log docker exec $CONTAINER journalctl -u pki-tomcatd@$INSTANCE.service > $ARTIFACTS/var/log/pki/$INSTANCE/systemd.log jss-5.0.0/tests/bin/runner-init.sh000077500000000000000000000010031412550063600170320ustar00rootroot00000000000000#!/bin/bash -ex docker run \ --name=${NAME} \ --hostname=${HOSTNAME} \ --detach \ --privileged \ --tmpfs /tmp \ --tmpfs /run \ -v /sys/fs/cgroup:/sys/fs/cgroup:ro \ -v ${GITHUB_WORKSPACE}:${SHARED} \ -i \ ${IMAGE} # Pause 5 seconds to let the container start up. # The container uses /usr/sbin/init as its entrypoint which requires few seconds # to startup. This avoids the following error: # [Errno 2] No such file or directory: '/var/cache/dnf/metadata_lock.pid' sleep 5 jss-5.0.0/tools/000077500000000000000000000000001412550063600134555ustar00rootroot00000000000000jss-5.0.0/tools/Dockerfiles/000077500000000000000000000000001412550063600157075ustar00rootroot00000000000000jss-5.0.0/tools/Dockerfiles/centos_7000066400000000000000000000017511412550063600173570ustar00rootroot00000000000000FROM centos:7 # Install generic dependencies to build jss RUN true \ && yum update -y \ && yum install -y epel-release yum-utils \ && yum install -y gcc make cmake3 \ && yum-builddep -y jss \ && mkdir -p /home/sandbox \ && yum clean -y all \ && rm -rf /usr/share/doc /usr/share/doc-base \ /usr/share/man /usr/share/locale /usr/share/zoneinfo \ && true # Link in the current version of jss from the git repository WORKDIR /home/sandbox COPY . /home/sandbox/jss # Install dependencies from the spec file in case they've changed # since the last release on this platform. RUN true \ && yum-builddep -y /home/sandbox/jss/jss.spec \ && true # Perform the actual build from source, not from RPM WORKDIR /home/sandbox/jss CMD true \ && rm -rf build \ && mkdir build \ && cd build \ && cmake3 .. \ && make all \ && ctest --output-on-failure \ && true jss-5.0.0/tools/Dockerfiles/centos_8000066400000000000000000000022021412550063600173500ustar00rootroot00000000000000FROM centos:8 # Install generic dependencies to build jss RUN true \ && dnf update -y --refresh \ && dnf install -y dnf-plugins-core gcc make rpm-build \ && ( dnf config-manager --enable powertools || dnf config-manager --enable PowerTools ) \ && dnf module enable -y pki-deps maven javapackages-tools \ && dnf build-dep -y jss \ && mkdir -p /home/sandbox \ && dnf clean -y all \ && rm -rf /usr/share/doc /usr/share/doc-base \ /usr/share/man /usr/share/locale /usr/share/zoneinfo \ && true # Link in the current version of jss from the git repository WORKDIR /home/sandbox COPY . /home/sandbox/jss # Install dependencies from the spec file in case they've changed # since the last release on this platform. RUN true \ && dnf build-dep -y --spec /home/sandbox/jss/jss.spec \ && true # Perform the actual build from source, not from RPM WORKDIR /home/sandbox/jss CMD true \ && rm -rf build \ && mkdir build \ && cd build \ && cmake .. \ && make all \ && ctest --output-on-failure \ && true jss-5.0.0/tools/Dockerfiles/fedora_rawhide000066400000000000000000000022021412550063600205710ustar00rootroot00000000000000FROM registry.fedoraproject.org/fedora:rawhide # Install generic dependencies to build jss RUN true \ && dnf update -y --refresh \ && dnf install -y dnf-plugins-core gcc make rpm-build cmake \ java-11-openjdk nss-tools \ apache-commons-lang3 gcc-c++ java-11-openjdk-devel \ jpackage-utils slf4j nss zlib-devel nss-devel \ nspr-devel slf4j-jdk14 junit \ && mkdir -p /home/sandbox \ && dnf clean -y all \ && rm -rf /usr/share/doc /usr/share/doc-base \ /usr/share/man /usr/share/locale /usr/share/zoneinfo \ && true # Link in the current version of jss from the git repository WORKDIR /home/sandbox COPY . /home/sandbox/jss # Perform the actual RPM build WORKDIR /home/sandbox/jss CMD true \ && export JAVA_HOME=/usr/lib/jvm/jre-11-openjdk \ && export WITH_INTERNET=1 \ && rm -rf build \ && mkdir build \ && cd build \ && cmake .. \ && make all \ && ctest --output-on-failure \ && make javadoc \ && true jss-5.0.0/tools/Dockerfiles/fedora_sandbox000066400000000000000000000026621412550063600206160ustar00rootroot00000000000000FROM registry.fedoraproject.org/fedora:rawhide # Install generic dependencies to build jss RUN true \ && dnf update -y --refresh \ && dnf install -y dnf-plugins-core gcc make rpm-build cmake \ nss-tools apache-commons-lang3 \ gcc-c++ jpackage-utils slf4j zlib-devel perl \ slf4j-jdk14 junit ninja-build gyp gtest mercurial \ python-unversioned-command \ && dnf build-dep nss nspr jss -y \ && mkdir -p /home/sandbox \ && dnf clean -y all \ && rm -rf /usr/share/doc /usr/share/doc-base \ /usr/share/man /usr/share/locale /usr/share/zoneinfo \ && true # Link in the current version of jss from the git repository WORKDIR /home/sandbox COPY . /home/sandbox/jss # Download and build NSPR and NSS RUN true \ && cd /home/sandbox \ && hg clone https://hg.mozilla.org/projects/nspr \ && hg clone https://hg.mozilla.org/projects/nss \ && cd nss \ && ./build.sh --enable-fips --enable-libpkix \ && true # Perform the actual RPM build WORKDIR /home/sandbox/jss CMD true \ && export SANDBOX=1 \ && rm -rf build \ && mkdir build \ && cd build \ && CFLAGS="-Wall -Wextra -Werror -Og -ggdb" cmake -DCMAKE_BUILD_TYPE=Debug .. \ && make all \ && ctest --output-on-failure \ && true jss-5.0.0/tools/Dockerfiles/stylecheck000066400000000000000000000012251412550063600177700ustar00rootroot00000000000000FROM registry.fedoraproject.org/fedora:latest # Install generic dependencies to check style RUN true \ && dnf update -y --refresh \ && dnf install -y perl ShellCheck python2-pylint python3-pylint \ && mkdir -p /home/sandbox \ && dnf clean -y all \ && rm -rf /usr/share/doc /usr/share/doc-base \ /usr/share/man /usr/share/locale /usr/share/zoneinfo \ && true # Link in the current version of jss from the git repository WORKDIR /home/sandbox COPY . /home/sandbox/jss # Perform the style checks WORKDIR /home/sandbox/jss CMD true \ && bash ./tools/test_shell_style.sh \ && true jss-5.0.0/tools/autoenv.sh000077500000000000000000000040101412550063600154700ustar00rootroot00000000000000#!/bin/sh # This script attempts to detect the correct environmental variables required # to build JSS from source. # Try and detect a JDK installation. if [ "x$JAVA_HOME" = "x" ] && [ -e "/etc/alternatives/java_sdk" ]; then export JAVA_HOME="/etc/alternatives/java_sdk" fi if [ "x$JAVA_HOME" = "x" ]; then # Prefer JDK 8 installation, if present... java8_jdk="$(find /usr/lib/jvm -maxdepth 1 -mindepth 1 -type d | grep '\(\-8\-\|-1\.8\.\)' | sort | tail -n 1)" if [ -d "$java8_jdk" ]; then export JAVA_HOME="$java8_jdk" fi fi if [ "x$JAVA_HOME" = "x" ]; then # Attempt to automatically detect it from java program... system_java="$(java -XshowSettings:properties -version 2>&1 > /dev/null | grep 'java.home' | sed 's/^.* = //g')" dirname_system_java="$(dirname "$system_java")" if [ -e "$system_java/bin/javac" ]; then export JAVA_HOME="$system_java" elif [ -e "$dirname_system_java/bin/javac" ]; then export JAVA_HOME="$dirname_system_java" fi fi # Validate that JAVA_HOME was set; otherwise, exit. if [ "x$JAVA_HOME" = "x" ]; then echo "Unable to detect JAVA_HOME installation automatically!" 1>&2 return 1 fi # Check if we're running in 64-bit mode. if [ "x$(getconf LONG_BIT)" = "x64" ]; then export USE_64=1 fi # Check if we're in a location with nss/nspr above us; if not, use the system # versions. if [ ! -d ../nspr ] || [ ! -d ../nss ]; then export USE_INSTALLED_NSPR=1 export USE_INSTALLED_NSS=1 export PKG_CONFIG_ALLOW_SYSTEM_LIBS=1 export PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1 NSPR_INCLUDE_DIR="$(pkg-config --cflags-only-I nspr | sed 's/-I//')" NSPR_LIB_DIR="$(pkg-config --libs-only-L nspr | sed 's/-L//')" NSS_INCLUDE_DIR="$(pkg-config --cflags-only-I nss | sed 's/-I//')" NSS_LIB_DIR="$(pkg-config --libs-only-L nss | sed 's/-L//')" export NSPR_INCLUDE_DIR export NSPR_LIB_DIR export NSS_INCLUDE_DIR export NSS_LIB_DIR export XCFLAGS="-g" else export USE_INSTALLED_NSPR="" export USE_INSTALLED_NSS="" fi jss-5.0.0/tools/build_pkcs11_constants.py000077500000000000000000000726021412550063600204160ustar00rootroot00000000000000#!/usr/bin/env python3 """ Copyright (C) 2018 Red Hat See licenses in base of jss repository: https://github.com/dogtagpki/jss Utility to automatically build PKCS11Constants.java from NSS's pkcs11t.h and pkcs11n.h headers. See documentation under docs/pkcs11_constants.md for more information. """ from __future__ import print_function import logging import os import subprocess import sys import tempfile import argparse import textwrap BLACKLIST = [ 'CK_PTR', 'CK_VOID', 'CK_CALLBACK_FUNCTION', 'CK_DECLARE_FUNCTION', 'CK_DECLARE_FUNCTION_POINTER', 'CK_UNAVAILABLE_INFORMATION' ] logger = logging.getLogger(__name__) def parse_c_value(c_value): """ Evaluates a given c numeric value and converts it to a hexadecimal value. Returns the resulting value. """ # Without introducing external dependencies, this is the best way # to parse the value of the constant. Since this step is used in a # explicitly-user-controlled environment (the user passed the paths # to the header files we parse here), this is no worse than the # user calling eval() themselves. Further, this is only run manually, # and not as part of every build, so again this should be considered # safe within our use cases and threat model. Thus, disable pylint # the warnings about eval for this function. # pylint: disable=eval-used value = eval(c_value.replace('UL', '').replace('L', '')) value = hex(value) value = value[2:].upper() value = "0x" + "0" * (8 - len(value)) + value return value class ConstantDefinition(object): """ Wrapper class to accumlate information about a constant's definition. This tracks all the information necessary to define a constant and represent its context in the ecosystem. """ # Since this is largely a data-storage class, we're bound to have too many # attributes because we're tracking metadata about the constants and their # values. Disable pylint warnings related to this. # pylint: disable=too-many-instance-attributes,too-many-arguments PREFIXES = ['CKA_', 'CKC_', 'CKD_', 'CKF_', 'CKG_', 'CKH_', 'CKK_', 'CKM_', 'CKN_', 'CKO_', 'CKP_', 'CKR_', 'CKS_', 'CKT_', 'CKU_', 'CKZ_', 'NSSCK_', 'SFTK_', 'CK_'] def __init__(self, header_file="pkcs11t.h", line_number=1, line="", name="DEFAULT", value=1): self.header_file = header_file self.line_number = line_number self.line = line.replace('/*', '/ *').replace('*/', '* /') self.name = name self.value = value self.checked = False self.resolved = False self.stdout = "" self.stderr = "" self.resolved_history = [] self.resolved_value = "" def resolve_value(self, other_constants): """ Given a list of other constants (also of type ConstantDefinition), get their values and resolve this constant's value based off of the other constants and their values. In particular, if this constant's value includes as a substring a key from other_constants, replace the occurrence with the value from the other constant. Note that other_constants must be a pre-ordered list in reverse alphabetical order. E.g., for the map { "a": "b | c", "b": "3", "c": "4"}, then "a" will eventually resolve to "3 | 4". The resolved value and the resolution chain are attached to instance variables: self.resolved_value self.resolved_history And self.resolved is set to True. """ value = self.value value_history = [] changed = True # Since we can't truly parse C in Python (or, parse C well outside of # a C compiler), we can't really parse the obj's value for tokens and # then check if the tokens match our constants and replace them. # So, we loop while the constant was changed. while changed: changed = False # One of our assertions was that other_constants was provided to # us in reverse alphabetical order. This means that the constant # "AA" is present before "A"; thus a simple loop lets us process # symbols in the expected order if they're present in this obj's # value. One example is CKT_NSS_UNTRUSTED: it has a value of # "CKT_NSS_MUST_VERIFY_TRUST", but CKT_NSS is another token; if # "CKT_NSS" is processed first, CKT_NSS_UNTRUSTED then takes # a value of "(0xCE534350)_MUST_VERIFY_TRUST" which isn't a valid # value. for obj in other_constants: if obj.name in value: # We wrap the replacement in parenthesis in case it is a # mathematical expression which needs to be parsed. These # parenthesis disappear when we compute its value later, # after we are done resolving all symbols into numeric # expressions. replacement = '(' + obj.value + ')' # Note that if the target symbol is already resolved, we # can save the steps of resolving its value again by using # its resolved value here. if obj.resolved: replacement = '(' + obj.resolved_value + ')' value_history.append((value, obj.name, replacement)) value = value.replace(obj.name, replacement) changed = True # Pass the processed numeric expression for value into "parse_c_value" # and save it as the resolved value. try: self.resolved_value = parse_c_value(value) except Exception as e: logger.error("Failed to parse value for constant: " + self.name, file=sys.stderr) raise e self.resolved_history = value_history self.resolved = True def check_output(self, nss_args): """ Checks the output of cc against the value of the constant in this object. This ensures that what we think the value to be is what was intended for the value to be. Raises an exception if the value differs. """ logger.info("Validating constant %s = %s", self.name, self.resolved_value) # This made an intentional design choice to run each constant's check # separately; we could've grouped several (or all) of the constants # together in one check like we did the output Java class, but this has # the downside of making detecting which symbol is incorrect harder. # Small, minimal template to check if the value differs. If it does, # this program will exit with status 1 which we detect later. This # also helps to ensure that our resolved value truly is numeric. program_template = """ #include "pkcs11t.h" #include "pkcs11n.h" int main() { if (%s != %s) { return 1; } return 0; } """ % (self.name, self.resolved_value) # Create a temporary directory; this is preserved in case of failure # such that the caller of this script can identify why it failed. temp_dir = tempfile.mkdtemp(prefix="tmp-jss-pkcs11constants-") path = os.path.join(temp_dir, "test.c") exec_path = os.path.join(temp_dir, "test.exe") temp_program = open(path, 'w') temp_program.write(program_template) temp_program.close() # Build a minimal cc call; note that nss_args is the output from # pkg-config such that we can correctly link this program and # have the correct includes for nss. # # Define NSS_PKCS11_2_0_COMPAT due to NSS changes: # https://fedoraproject.org/wiki/Changes/NssGCMParams cc_call = ["cc", "-DNSS_PKCS11_2_0_COMPAT", "-o", exec_path, path] + nss_args logger.debug("Command: %s", ' '.join(cc_call)) proc = subprocess.Popen(cc_call, stdout=subprocess.PIPE, stderr=subprocess.PIPE) proc.wait() self.stdout = proc.stdout.read() if not isinstance(self.stdout, str): self.stdout = self.stdout.decode('utf8') self.stderr = proc.stderr.read() if not isinstance(self.stderr, str): self.stderr = self.stderr.decode('utf8') if self.stdout: logger.info("%s validation output:\n%s", self.name, self.stdout) if self.stderr: logger.warning("%s validation error/warning:\n%s", self.name, self.stderr) # Check whether or not the program compiled correctly; note that # this comes after the stdout/stderr writes, so our caller can # see what the error was. ret = proc.returncode if proc.returncode != 0: raise Exception(("Unknown error with symbol '%s': cc ret: %d " + "@ %s; command: %s") % (self.name, ret, temp_dir, ' '.join(cc_call))) # Since the program compiled correctly, run it to ensure the value # is correct. ret = subprocess.call(exec_path) if ret != 0: raise Exception(("Value for symbol '%s' different from expected:" + " wasn't '%s' @ %s") % (self.name, self.resolved_value, temp_dir)) # With no errors, clean up the temporary data. if os.path.exists(exec_path): os.remove(exec_path) if os.path.exists(path): os.remove(path) if os.path.exists(temp_dir): os.rmdir(temp_dir) self.checked = True def is_included(self): """ Returns true iff name begins with an allowed prefix. """ for prefix in self.PREFIXES: if self.name.startswith(prefix): return True return False def get_source_content(self): """ Converts a value to a Java-like value in its source context. """ logger.info("Generating constant %s = %s", self.name, self.resolved_value) # In particular, "source context" means in this case "comments" # and the particular java delcaration. Our constants must be of # type long because several of them exceed the value of a signed # integer and Java lacks unsigned integers. One example is # CKT_NSS which has value 0xCE534350. # We make the requirement strict here that all values are numeric # and resolved of all internal symbols. if not self.resolved: raise Exception("Must resolve all references before calling!") comment_header = "\n /**\n" comment_info = " * Content automatically generated; see NSS " comment_info += "documentation for more information.\n" comment_info += " *\n" comment_info += " * Source file: %s\n" % self.header_file # Log debugging information. logger.debug("Input: %s", self.line) logger.debug("Source: %s:%s", self.header_file, self.line_number) logger.debug("Name: %s", self.name) logger.debug("Value: %s", self.value) # Log resolution history. This is useful for # detecting errors made during resolution. if self.resolved_history: for (value, name, replacement) in self.resolved_history: logger.debug("Resolution: in [%s]", value) logger.debug(" replaced [%s] with [%s]", name, replacement) comment_footer = " */\n" comment = comment_header + comment_info + comment_footer # Actual definition of the constant; needs a "L" so that unsigned # values get processed correctly. source_template = "public static final long %s = %sL;" output = source_template % (self.name, self.resolved_value) logger.debug("Output: %s", output) source_line = " %s\n" % output return comment + source_line def read_lines(file_handle): """ Given a pointer to a file, returns contents of the file as a list, removing the trailing whitespace from all lines. """ # readlines() leaves the newline character attached, and in general, # we don't care about whitespace at the end. We care about prefixed # whitespace when reading the copyright header though, hence rstrip() # and not strip(). return list(map(lambda x: x.rstrip(), file_handle.readlines())) def parse_token(line, offset, parenthesis=True): """ From a line, parse a single "token" starting at the given character offset. The definition of a token is a continguous, non-whitespace segment of characters; parenthesis allow the token to continue over whitespace. Returns a tuple (token, index_of_last_character). In particular, "(some content)" is treated as a single token, "(something else" is an error (lacks a trailing parenthesis), and "some content" is two separate tokens. """ # Parenthesis occur when the constant is a compound expression # like in the case of CKO_NSS: (CKO_VENDOR_DEFINED | NSSCK_VENDOR_NSS). # We need the entire expression to be parsed as a single "value", # hence keeping track of parenthesis. Other symbols (such as curly # braces or square brackets) are ignored because they don't appear # in useful #define statements. token_start = offset while token_start < len(line) and line[token_start].isspace(): token_start += 1 paren_count = 0 token_end = token_start while token_end < len(line) and (not line[token_end].isspace() or paren_count != 0): if line[token_end] == '(': if not parenthesis: break paren_count += 1 if line[token_end] == ')': paren_count -= 1 token_end += 1 if paren_count != 0: raise Exception("Cannot parse line: spans multiple lines: %s" % line) token = line[token_start:token_end] return token, token_end def parse_define(line): """ Assuming that this line begins with '#define', parse the two parts of the define statement: the name of the define and the value it takes. Returns a tuple (name, value). """ if not line.startswith('#define'): raise Exception("Cannot parse line: doesn't begin with #define!\n" + line) name, name_end = parse_token(line, len('#define'), parenthesis=False) value, _ = parse_token(line, name_end, parenthesis=True) return name, value def parse_copyright(file_contents): """ In the contents of a file, find all comments before the first macro statement and include them in the returned copyright headers. """ in_comment = False copyright_headers = [] # We need to parse the copyright value for legal reasons. While in # practice the copyright could be anywhere, we assume it is in the # comments before the first macro statement in the file. This makes # an attempt to remove blank lines that are not part of a comment, # and does basic sanity checking on the locations of block comments. # This _will_ get confused as it doesn't completely parse comments, # but that confusion should be limited to later in the file, which # we ignore. for line_num in range(0, len(file_contents)): line = file_contents[line_num] have_start = "/*" in line have_end = "*/" in line have_pound = '#' in line if have_start and have_end: # In this case, both a /* and */ appeared, so we make an effort # to detect which came first and update our state accordingly. start_index = line.index("/*") end_index = line.index("*/") start_before_end = start_index < end_index and line.endswith("*/") if start_before_end: in_comment = False else: in_comment = True # Either way, save the line and hope it is a valid comment :) copyright_headers.append(line) elif have_start: # We're beginning a comment, save this line. in_comment = True copyright_headers.append(line) elif have_end: # We're ending a comment, save this line. in_comment = False copyright_headers.append(line) elif in_comment: # We're in a comment, save this line. copyright_headers.append(line) elif not in_comment and have_pound: # We're not in a comment, assume the pound means a macro # statement and exit. break # else: we're not in a comment and this is a random line, so don't # bother saving it. return "\n".join(copyright_headers) + "\n\n" def parse_header(header): """ Parse the contents of the file path (header) for #define statements and the copyright headers. The #define statements are returned as a list of items of type ConstantDefinition. The copyright header is returned as a string. """ logger.info("Parsing %s", header.name) file_contents = read_lines(header) # Capture all definitions first, and create ConstantDefinition from them. defines = [] for line_num in range(1, len(file_contents)+1): line = file_contents[line_num-1].lstrip() if line.startswith('#define'): name, value = parse_define(line) if name in BLACKLIST: logger.info("Skipping blacklisted constant: %s", name) continue logger.info("Found definition %s = %s", name, value) new_definition = ConstantDefinition(header.name, line_num, line, name, value) defines.append(new_definition) # Also save the copyright headers from this file for legal reasons. copyright_headers = "/* Copyright statements from %s */\n" % header.name copyright_headers += parse_copyright(file_contents) return defines, copyright_headers def remove_by_name(objs, name): """ Helper function to take a list of objects and remove the occurrences of constants with the same name, updating the list in place. This is necessary to make our list behave like an ordered set. """ # Build a list of indices where the object occurs; this should be # only one index, but we handle the case where it appears multiple # times in the list. indices = [] for index in range(0, len(objs)): obj = objs[index] if obj.name == name: indices.append(index) # Create a copy of the array and modify the copy; in particular, by # removing objects in reversed order, we can ensure that we don't # need to update the value of the indices (e.g., if we processed # the indices (1, 2, 3), we'd have to subtract one from 2 and 3 # after processing the first index (1)... this gets messy, so # processing in reverse order (3, 2, 1) ensures we don't have to. for index in reversed(sorted(indices)): objs.pop(index) def filter_objects(objs): """ From all known defined objects (of type ConstantDefinition), filter the output to only contain objects which should be included, i.e., whose name begins with a whitelisted prefix. Return the result as a new list. """ results = [] for obj in objs: if obj.is_included(): # Before appending an object, we must first remove an previous # references to it in the results list. This is mostly an issue # so that we don't have duplicate definitions in our file, but # also because some constants appear multiple times in pkcs11n.h # due to GCC deprecation hacks. remove_by_name(results, obj.name) results.append(obj) else: # It isn't an error and is merely informational to ignore some # symbols at this stage. logger.info("Symbol ignored due to unmatched prefix: %s", obj.name) return results def resolve_internal_references(objs): """ Resolve all internal references between symbols in objs, modifying the objects in place. That is, if SYM_A = SYM_B and SYM_B = 3 are of type ConstantDefinition, modify them so SYM_A = 3 and SYM_B = 3. This also works if the symbol names are inside the value. Note that obj.resolve_value must be passed a list of constants ordered by reverse alphabetical order on the name of the symbol. """ # To build the sorted order, we're going to use O(2n) space: first # build a dictionary mapping everything, and then construct a new # list based on the order. This isn't terribly expensive as the # objects are small and the O(n log n) sort could/should dominate. obj_map = {} for obj in objs: obj_map[obj.name] = obj sorted_objs = [] for key in reversed(sorted(obj_map.keys())): sorted_objs.append(obj_map[key]) for obj in objs: obj.resolve_value(sorted_objs) def check_references(objs): """ Perform extended checks against all known symbols; this assumes that the passed pkcs11t.h and pkcs11n.h are the system-installed version. In particular, given our current set of symbols, create a minimal C program which checks our computed value against the actual value in the header; this ensures all known symbols are parsed correctly. Depends on the following external programs being in PATH: - pkg-config - cc """ # This method just wraps calling obj.check_output() for all constants. # Print statement because this step takes a while (~30s); might as well # tell the user. :) logger.info("Performing extended value checks...") # Such that we can link against nss and find the includes, use pkg-config. # Note that pkg-config is already a soft-dependency (it is utilized in # the README for linking against the system NSS), so using it here # isn't bad. proc = subprocess.Popen(["pkg-config", "--libs", "--cflags", "nss"], stdout=subprocess.PIPE) proc.wait() pkg_config = proc.stdout.read() if not isinstance(pkg_config, str): pkg_config = pkg_config.decode('utf8') # Make a safer argument list out of them so we don't need to fork out # to the shell. nss_args = pkg_config.strip().split(' ') for obj in objs: obj.check_output(nss_args) def build_class(objs, headers): """ From a dictionary of objects (obj_map), generate a Java class for the constants. Returns the text contents (str) of the generated class file. """ # Our generated Java class has the following structure: # # - Our Copyright and information block # - Our headers copyright blocks # - Class definition # - Constant comment # - Constant definition # - ... (repeat) # - End class definition # # Note that our result is a single string, not a list of lines. file_header = textwrap.dedent("""\ /** * PKCS11Constants.java - part of the JSS project * Copyright (C) 2018 Red Hat, Inc. * * This file is automatically generated (tools/build_pkcs11_constants.py) * from the contents of NSS's pkcs11t.h and pkcs11n.h headers. This * replaces the sun.security.pkcs11.wrapper.PKCS11Constants interface * which was removed from public visibility in JDK 9 due to the * introduction of modules. * * For more information, please see the documentation under * jss/docs/pkcs11_constants.md. * * Below are the copyright statements for the sourced files: */ """) for header in headers: file_header += header file_header += textwrap.dedent("""\ package org.mozilla.jss.pkcs11; public interface PKCS11Constants { """) file_body = "" for obj in objs: file_body += obj.get_source_content() file_footer = "}\n" return file_header + file_body + file_footer def test_compilation(file_contents): """ Given the contents of the generated Java class, try to compile it. This allows us to verify that our Java class is valid and doesn't break the build. Depends on the following programs being in the PATH: - javac """ # Since this is a stand-alone package, we don't require CLASSPATH to # include anything. # Create a temporary directory so we can create a file of the correct # name for Java, but also so that in the event of failure, the user # can view the file to see what is wrong as we haven't written it # to the output location yet. java_dir = tempfile.mkdtemp(prefix="tmp-jss-pkcs11constants-") java_path = os.path.join(java_dir, "PKCS11Constants.java") class_path = java_path.replace(".java", ".class") temp_program = open(java_path, 'w') temp_program.write(file_contents) temp_program.close() # The subprocess.call will output stdout/stderr of the called program. javac_call = ["javac", java_path] ret = subprocess.call(javac_call) if ret != 0: raise Exception("Error! Generated java code does not compile!") # If successful, clean up after ourselves. if os.path.exists(class_path): os.remove(class_path) if os.path.exists(java_path): os.remove(java_path) if os.path.exists(java_dir): os.rmdir(java_dir) def write_class(file_contents, output): """ Helper method to write the contents of the file to the specified file handle (output). """ logger.info("Generating %s", output.name) output.write(file_contents) output.close() def parse_args(): """ Parses arguments passed to the application """ parser = argparse.ArgumentParser() # This enables the checks against a system-installed NSS; this is slow # (~30s) and is hence not enabled by default (and also not possible # against a source NSS tree without more work). However it is useful for # verifying our parsing routines. parser.add_argument("-s", "--system", action="store_true", help="pkcs11t.h is installed; perfrom system checks") # This is the path to the pkcs11t.h header file from the NSS we wish to # build against. pkcs11t.h is the main header which contains most of the # RSA/"Cryptoki" values. parser.add_argument("--pkcs11t", type=argparse.FileType('r'), required=True, help="Path to pkcs11t.h header") # This is the path to the pkcs11n.h header file from the NSS we whish to # build against. pkcs11n.h is the header which contains NSS/Netscape # specific values. parser.add_argument("--pkcs11n", type=argparse.FileType('r'), required=True, help="Path to pkcs11n.h header") # Path to output the generated file to. parser.add_argument("-o", "--output", type=argparse.FileType('w'), required=True, help="Path to write PKCS11Constants.java") parser.add_argument("-v", "--verbose", action="store_true", help="Run in verbose mode.") parser.add_argument("--debug", action="store_true", help="Run in debug mode.") return parser.parse_args() def main(): """ Main method for utility parser. """ logging.basicConfig(format='%(levelname)s: %(message)s') args = parse_args() if args.debug: logging.getLogger().setLevel(logging.DEBUG) elif args.verbose: logging.getLogger().setLevel(logging.INFO) # The high level flow of the program is as follows: # # - Parse the pkcs11t header # - Parse the pkcs11n header # - Combine the resulting definitions in that order # - Resolve internal references/convert symbols to numeric values # - If extended checks are requested, run them # - Check that the generated class compiles # - Write the generated class as output # # The philosophy of this utility is anything that is a "warning" should # instead be treated as an error, with the exception of compiler warnings # when performing extended system checks. All exceptions are raised as # exceptions, and are not caught by this main method and thus will be # reported to the caller as the occur. This ensures that the output won't # be malformed and won't be generated unless it is correct. # # In particular: # # - All #define statements are considered constant definitions. # - If a #define cannot be parsed, this is an error. # - If a symbol value cannot be resolved to a numeric value, this is # an error. # - If a parsed value is not the same as the system version, this is # an error. # - If the resulting Java program does not compile, this is an error. t_objs, t_copyright = parse_header(args.pkcs11t) t_objs_filtered = filter_objects(t_objs) n_objs, n_copyright = parse_header(args.pkcs11n) n_objs_filtered = filter_objects(n_objs) objs = t_objs_filtered[:] objs.extend(n_objs_filtered) headers = [t_copyright, n_copyright] resolve_internal_references(objs) if args.system: # Since this is a system call, ignore the paths to the headers and # assume they are the same as what is found by pkg-config. check_references(objs) output_contents = build_class(objs, headers) test_compilation(output_contents) write_class(output_contents, args.output) logger.info("Success generating constant definitions") if __name__ == "__main__": main() jss-5.0.0/tools/common_roots.sh000077500000000000000000000022441412550063600165340ustar00rootroot00000000000000#!/bin/bash # This script reads the contents of the OS CA bundle store, # /usr/share/pki/ca-trust-source/ca-bundle.trust.p11-kit # and places the contained CAs into the specified NSS DB. # # This NSS DB is used by various JSS tests that aren't enabled # by default because they require an active internet connection. nssdb="$1" if [ -z "$nssdb" ] && [ -e "build" ]; then nssdb="build/results/cadb" elif [ -z "$nssdb" ] && [ -e "../build" ]; then nssdb="../build/results/cadb" elif [ -z "$nssdb" ] || [ "x$nssdb" == "x--help" ]; then echo "Usage: $0 [/path/to/nssdb]" 1>&2 echo "" 1>&2 echo "Must provide path to NSS DB!" 1>&2 exit 1 fi if [ -e "$nssdb" ]; then rm -rf "$nssdb" fi mkdir -p "$nssdb" echo "" > "$nssdb/password.txt" certutil -N -d "$nssdb" -f "$nssdb/password.txt" trust extract --format=pem-bundle --filter=ca-anchors "$nssdb/complete.pem" # From: https://serverfault.com/questions/391396/how-to-split-a-pem-file csplit -f "$nssdb/individual-" "$nssdb/complete.pem" '/-----BEGIN CERTIFICATE-----/' '{*}' for cert in "$nssdb"/individual*; do certutil -A -a -i "$cert" -n "$cert" -t CT,C,C -d "$nssdb" -f "$nssdb/password.txt" done jss-5.0.0/tools/java.security.in000066400000000000000000000033261412550063600166000ustar00rootroot00000000000000# # This is the "master security properties file". # # An alternate java.security properties file may be specified # from the command line via the system property # # -Djava.security.properties= # # This properties file appends to the master security properties file. # If both properties files specify values for the same key, the value # from the command-line properties file is selected, as it is the last # one loaded. # # Also, if you specify # # -Djava.security.properties== (2 equals), # # then that properties file completely overrides the master security # properties file. # # To disable the ability to specify an additional properties file from # the command line, set the key security.overridePropertiesFile # to false in the master security properties file. It is set to true # by default. # # List of providers and their preference orders: # # This differs from the master file in that we initialize JSS first. # security.provider.1=org.mozilla.jss.JSSProvider @JSS_CFG_PATH@ security.provider.2=sun.security.provider.Sun security.provider.3=sun.security.rsa.SunRsaSign security.provider.4=sun.security.ec.SunEC security.provider.5=com.sun.net.ssl.internal.ssl.Provider security.provider.6=com.sun.crypto.provider.SunJCE security.provider.7=sun.security.jgss.SunProvider security.provider.8=com.sun.security.sasl.Provider security.provider.9=org.jcp.xml.dsig.internal.dom.XMLDSigRI security.provider.10=sun.security.smartcardio.SunPCSC # Note: JSS and a SunPKCS11-based provider would clash, because it too would # initialize NSS. If you see something of the following form in your # java.security, it is suggested to remove it: # # security.provider.11=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/nss.cfg jss-5.0.0/tools/javadoc/000077500000000000000000000000001412550063600150645ustar00rootroot00000000000000jss-5.0.0/tools/javadoc/overview.html000066400000000000000000000003621412550063600176210ustar00rootroot00000000000000 JSS: Java Security Services

Java native interface which provides a bridge for java-based applications to use native Network Security Services (NSS). jss-5.0.0/tools/jss.cfg.in000066400000000000000000000001251412550063600153400ustar00rootroot00000000000000nss.config_dir=${NSS_DB_PATH} jss.password=${DB_PWD} jss.experimental.sslengine=true jss-5.0.0/tools/logging.properties000066400000000000000000000024661412550063600172310ustar00rootroot00000000000000# --- BEGIN COPYRIGHT BLOCK --- # Copyright (C) 2020 Red Hat, Inc. # All rights reserved. # Modifications: configuration parameters # --- END COPYRIGHT BLOCK --- # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (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.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # This was taken from Dogtag PKI's configuration. # See: https://github.com/dogtagpki/pki/blob/master/base/common/share/etc/logging.properties java.util.logging.ConsoleHandler.level = ALL java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter java.util.logging.SimpleFormatter.format = %4$s: %5$s%6$s%n .level = FINE .handlers = java.util.logging.ConsoleHandler jss-5.0.0/tools/reproducible_jar.sh000077500000000000000000000025271412550063600173350ustar00rootroot00000000000000#!/bin/bash # A shell script to create a reproducible jar distirbution for JSS. # # This will extract the created JSS build and normalize timestamp and file # insertion order. This will help to ensure that anyone building in the same # environment will receive the same jar file assuming the contents of Java # haven't changed. # # Usage: # reproducible_jar.sh /path/to/input.jar /path/to/tmp/dir /path/to/output.jar set -e function extract() { local jar="$1" local path="$2" if [ -d "$path" ]; then rm -rf "$path" fi mkdir -p "$path" unzip -q "$jar" -d "$path" } function normalize_timestamps() { local path="$1" find "$path" -exec touch -t 201801010000 {} + } function add_manifest() { local path="$1" local output="$2" pushd "$path" >/dev/null zip -X -q "$output" "META-INF" zip -X -q "$output" "META-INF/MANIFEST.MF" popd >/dev/null } function add_classes() { local path="$1" local output="$2" pushd "$path" >/dev/null for file in $(find "org" | sort); do zip -X -q "$output" "$file" done popd >/dev/null } abs_jar="$(realpath "$1")" abs_path="$(realpath "$2")" abs_output="$(realpath "$3")" extract "$abs_jar" "$abs_path" normalize_timestamps "$abs_path" add_manifest "$abs_path" "$abs_output" add_classes "$abs_path" "$abs_output" jss-5.0.0/tools/run_container.sh000077500000000000000000000040451412550063600166650ustar00rootroot00000000000000#!/bin/bash # This tool attempts to detect the presence of various tools to run the CI # images. If present, it'll use them to run the specified container image. function rc_buildah() { buildah_path="$(command -v buildah)" podman_path="$(command -v podman)" [ "x$buildah_path" != "x" ] && [ "x$podman_path" != "x" ] } function rc_docker() { docker_path="$(command -v docker)" [ "x$docker_path" != "x" ] } function rc_run() { local image="$1" local ret=0 if [ ! -f "tools/Dockerfiles/$image" ]; then echo "Error: tools/Dockerfiles/$image is not a file; must be an" 1>&2 echo "existing location to launch container." 1>&2 exit 1 fi if rc_docker; then docker build --pull --tag "jss_$image:latest" -f "tools/Dockerfiles/$image" . ret="$?" if [ "x$ret" != "x0" ]; then echo "Container build exited with status: $ret" return $ret fi docker run "jss_$image:latest" ret="$?" if [ "x$ret" != "x0" ]; then echo "Container run exited with status: $ret" return $ret fi elif rc_buildah; then buildah bud --pull-always --tag "jss_$image:latest" -f "tools/Dockerfiles/$image" . ret="$?" if [ "x$ret" != "x0" ]; then echo "Container build exited with status: $ret" return $ret fi podman run "jss_$image:latest" ret="$?" if [ "x$ret" != "x0" ]; then echo "Container run exited with status: $ret" return $ret fi else echo "No supported container platform; please rerun with podman" 1>&2 echo "and buildah or docker installed." 1>&2 fi } if [[ "x$1" =~ "help" ]] || [ "x$1" = "x-h" ]; then echo "Usage: $0 " 1>&2 echo "" 1>&2 echo "Run the container task using buildah+podman or docker" 1>&2 echo "Note: must be the name of a file located under" 1>&2 echo " tools/Dockerfiles in the main repo." 1>&2 exit 0 fi rc_run "$1" jss-5.0.0/tools/run_test.sh.in000077500000000000000000000030741412550063600162700ustar00rootroot00000000000000#!/bin/bash # This utility gets templated to build/run_test.sh to help with running a # single test after building JSS. This gives the caller more flexibility # with command line arguments and ensures that the correct build artifacts # get used. export LD_LIBRARY_PATH="${NSS_LIBRARIES}:${CMAKE_BINARY_DIR}:${NSPR_LIBRARIES}" export CLASSPATH="${TEST_CLASSPATH}" export JAVA_SECURITY_CFG="${CONFIG_OUTPUT_DIR}/java.security" if [ "$1" == "--gdb" ]; then shift gdb --args "${Java_JAVA_EXECUTABLE}" -classpath "$CLASSPATH" -ea -Djava.library.path="$LD_LIBRARY_PATH" -Djava.security.properties="$JAVA_SECURITY_CFG" -Djava.util.logging.config.file="${PROJECT_SOURCE_DIR}/tools/logging.properties" "$@" elif [ "$1" == "--valgrind" ]; then shift valgrind --leak-check=full --track-origins=yes --show-leak-kinds=all "${Java_JAVA_EXECUTABLE}" -classpath "${TEST_CLASSPATH}" -ea -Djava.library.path="$LD_LIBRARY_PATH" -Djava.security.properties="$JAVA_SECURITY_CFG" -Djava.util.logging.config.file="${PROJECT_SOURCE_DIR}/tools/logging.properties" "$@" elif [ "$1" == "--perf" ]; then shift perf record -- "${Java_JAVA_EXECUTABLE}" -classpath "${TEST_CLASSPATH}" -ea -Djava.library.path="$LD_LIBRARY_PATH" -Djava.security.properties="$JAVA_SECURITY_CFG" -Djava.util.logging.config.file="${PROJECT_SOURCE_DIR}/tools/logging.properties" "$@" else "${Java_JAVA_EXECUTABLE}" -classpath "$CLASSPATH" -ea -Djava.library.path="$LD_LIBRARY_PATH" -Djava.security.properties="$JAVA_SECURITY_CFG" -Djava.util.logging.config.file="${PROJECT_SOURCE_DIR}/tools/logging.properties" "$@" fi jss-5.0.0/tools/test_python_style.sh000077500000000000000000000010331412550063600176110ustar00rootroot00000000000000#!/bin/sh set -e # # Usage: # test_python_style.sh [path] # # Tests the style of Python scripts in the build tree for compliance with pylint # guidance. Runs: # # pylint # # On all checked files. If [path] is specified, assumed to be the root of the # jss repository. Otherwise, defaults to `pwd`. # root_source_dir="$1" if [ "x$root_source_dir" = "x" ]; then root_source_dir="$(pwd)" fi python_check() { target_file="$1" pylint "$root_source_dir/$target_file" } python_check "tools/build_pkcs11_constants.py" jss-5.0.0/tools/test_shell_style.sh000077500000000000000000000016051412550063600174040ustar00rootroot00000000000000#!/bin/sh set -e # # Usage: # test_shell_style.sh [path] # # Tests the style of shell scripts in the build tree for compliance with strict # guidance. Runs: # # `shellcheck ` # # On all checked files. If [path] is specified, assumed to be the root of the # jss repository. Otherwise, defaults to `pwd`. # root_source_dir="$1" if [ "x$root_source_dir" = "x" ]; then root_source_dir="$(pwd)" fi shell_check() { target_file="$1" shellcheck -x "$root_source_dir/$target_file" if [ ! -x "$root_source_dir/$target_file" ]; then echo "$root_source_dir/$target_file must be executable!" return 1 fi echo "$root_source_dir/$target_file OK" } shell_check "build.sh" shell_check "tools/autoenv.sh" shell_check "tools/reproducible_jar.sh" shell_check "tools/run_container.sh" shell_check "tools/test_python_style.sh" shell_check "tools/test_shell_style.sh" jss-5.0.0/tools/tests/000077500000000000000000000000001412550063600146175ustar00rootroot00000000000000jss-5.0.0/tools/tests/cmac.c000066400000000000000000000003161412550063600156660ustar00rootroot00000000000000#include "nspr.h" #include "nss.h" #include "pkcs11t.h" int main() { int test = (CKM_AES_CMAC == 0x0000108AULL); test = test && (CKM_AES_CMAC_GENERAL == 0x0000108BULL); return test ? 0 : 1; } jss-5.0.0/tools/tests/oaep.c000066400000000000000000000003601412550063600157060ustar00rootroot00000000000000#include "nspr.h" #include "nss.h" #include "pkcs11t.h" #include "pk11pub.h" int main() { PK11_PubWrapSymKeyWithMechanism(NULL, 0, NULL, NULL, NULL); PK11_PubUnwrapSymKeyWithMechanism(NULL, 0, NULL, NULL, 0, 0, 0); return 0; }